Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the four problems that can detect your JavaScript level?

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

Today, I will talk to you about what are the four problems that can detect your JavaScript level, which may not be well understood by many people. in order to make you understand better, the editor has summarized the following contents for you. I hope you can get something according to this article.

JavaScript is now a very popular programming language based on which a large number of libraries and frameworks are derived. However, no matter how the high-level ecosystem develops, it can not be separated from the original JavaScript. Here, I selected four JavaScript interview questions to test programmers' skills in using normal JavaScript.

1. Implement Array.prototype.map

How to implement the Array.prototype.map method manually?

It is not difficult to be proficient in using the built-in methods of arrays. However, if you are familiar with the syntax but not the principle, it is difficult to really understand JavaScript.

For Array.prototype.map, it creates a new array that is populated with the result of calling the provided function on each element in the calling array.

If we refer to lodash, we can write a map function, as follows:

Function map (array, iteratee) {let index =-1 const length = array = = null? 0: array.length const result = new Array (length) while (+ + index

< length) { result[index] = iteratee(array[index], index, array) } return result } 使用示例:

2. Object.defineProperty and agents

How to achieve this coding effect?

We can see that when we try to print obj.a three times in a row, we get three different results. How incredible it looks!

Can you create a mysterious object obj to achieve this effect?

In fact, there are three solutions to this problem:

Visitor Properties

Object.defineProperty

Agent

According to ECMAScript, the properties of an object can take two forms:

Logically, an object is a collection of properties. Each property is a data property or accessor property:

Data properties associate key values with ECMAScript language values and a set of Boolean attributes.

Accessor properties associate key values with one or two accessor functions and a set of Boolean properties. The accessor function is used to store or retrieve the ECMAScript language value associated with the property.

So-called data attributes are usually written by us:

Let obj = {a: 1, b: 2}

We only have two operations on the properties of an object: reading the properties and setting the properties. For accessor properties, we use the get and set methods to define properties, which are written as follows:

Let obj = {get a () {console.log ('triggle get a () method') console.log (' you can do anything as you want') return 1}, set a (value) {console.log ('triggle set a () method') console.log (' you can do anything as you want') console.log (`you are trying to assign ${value} to obj.a`)}}

Accessing properties provides us with strong metaprogramming capabilities, so we can meet our requirements in the following ways:

Let obj = {_ initValue: 0, get a () {this._initValue++; return this._initValue}} console.log (obj.a, obj.a, obj.a)

The second method is to use Object.defineProperty, which works the same way we use to access properties, except that instead of declaring access properties directly, they are accessed through Object.defineProperty configuration.

This is more flexible to use, so we can write it like this:

Let obj = {} Object.defineProperty (obj, 'asides, {get: (function () {let initValue = 0; return function () {initValue++; return initValue}}) () console.log (obj.a, obj.a, obj.a)

In the get method here, we use a closure so that the variable we need to use, initValue, is hidden in the closure and does not pollute other areas.

The third method is to use proxies.

Using proxies, we can intercept access to object properties. As long as we use a proxy to intercept access to obj.an and then return 1, 2, and 3 in turn, we can complete the requirement before the following conditions:

Let initValue = 0; let obj = new Proxy ({}, {get: function (item, property, itemProxy) {if (property ='a') {initValue++; return initValue} return item [property]}}) console.log (obj.a, obj.a, obj.a)

Why is it important to understand this problem? Because Object.defineProperty and Proxy give us powerful metaprogramming capabilities, we can modify objects appropriately to do something special.

In the famous front-end framework Vue, one of its core mechanisms is the two-way binding of data. In Vue2.0, Vue implements this mechanism by using Object.defineProperty. In Vue3.0, use Proxy to accomplish this mechanism.

If you don't know frameworks like Vue, you won't really understand. If you master these principles, you only need to learn half of Vue and you can get twice as many results.

3. Ranges and closures

What is the result of running this code?

Function foo (foo b) {console.log (b) return {foo:function (c) {return foo (c);}};} let res = foo (0); res.foo (1); res.foo (2); res.foo (3)

The above code has multiple nested functions and three foo nested functions, which seems tedious at first glance. So how do we understand this?

First of all, make sure how many functions are in the above code? We can see that keyword functions are used in both places in the above code, so there are two functions in the above code, the first line function foo (Aline b) and the fourth line foo:function (c). And the two functions have the same name.

The second question: which function is called by foo (crecoery a) on line 5? If you're not sure, let's look at a simple example:

Var obj= {fn:function () {console.log (fn);}}; obj.fn ()

If we run this code, will an exception be thrown? The answer is yes.

This is because the upper limit of the obj.fn () method is global and the fn method inside the obj cannot be accessed.

Going back to the previous example, with the same logic, when we call foo (crecoery a), we actually call the foo function on the first line.

Which foo will be called when we call res.foo (1)? Obviously, the foo function on line 4 is called.

Because the two foo functions work differently, we can change the name of one of them to bar to make it easier for us to understand the code.

Function foo (foo b) {console.log (b) return {bar:function (c) {return foo (c);}};} let res = foo (0); res.bar (1); res.bar (2); res.bar (3)

This change will not affect the final result, but it will make it easier for us to understand the code. If you encounter similar problems in the future, try this technique.

Each time a function is called, a new scope is created, so we can draw diagrams to help us understand the logic of how the code works.

When we execute let res = foo (0);, we are actually executing foo (0meme undefiend). At this point, a new scope will be created in the program, a = 0 undefined b = scope in the current scope. So, the picture I drew looks like this.

Then console.log (b) is executed, so it prints out "undefined" in the console for the first time.

Then execute res.bar (1) to create a new scope, where c = 1:

Then, from the above function, call foo (c _ line a) again, which is actually foo (1 ~ 0). The scope is as follows:

In the new scope, the value of an is 1 and the value of b is 0, so the console will print out 0.

Execute res.bar (2) again. Note that res.bar (2) and res.bar (1) are parallel, so we should draw a range diagram like this:

Therefore, in this code, the console also prints a value of 0.

The same is true for the execution of res.bar (3), where the console still displays 0.

Therefore, the end result of the above code is:

In fact, the above problems can be changed in other ways. For example, you can change it to the following:

Function foo (a foo:function b) {console.log (b) return {foo:function (c) {return foo (c);}};} foo (0) .foo (1) .foo (2) .foo (3)

Before we solve this problem, the first thing we need to do is to distinguish between two different foo functions, so we can change the above code to look like this:

Function foo (a) b) {console.log (b) return {bar:function (c) {return foo (c);}};} foo (0) .bar (1) .bar (2) .bar (3)

When you execute foo (0), the scope is the same as before, and then the console will print out "undefined".

Then execute .bar (1) to create a new scope. This parameter 1 is actually the value of c.

Then the .bar (1) method invokes foo (c _ force a) again, which is actually foo (1 ~ 0). Parameter 1 here will actually be the value of an in the new scope, and 0 will be the value of b in the new scope.

Therefore, the console then outputs the value of b, which is 0.

Call .bar (2) again, and in the new scope, the value of c is 2:

Bar (2) then invokes foo (cpeny a), which is actually foo (2p1), where 2 is the value of an in the new scope and 1 is the value of b in the new scope.

Therefore, the console then outputs the value of b, which is 0.

Then it will execute .bar (3), the process is the same as before, so I will not expand its description, this step the console will print out 2.

As mentioned above, the end result of the code running is:

Well, after a long journey, we finally got the answer. This question is a good test of the interviewees' understanding of closure and scope.

4. Write Compose

Suppose we have a function that looks like this:

Function compose (middleware) {/ / some code}

Compose function accepts function array middleware:

Let middleware = [] middleware.push ((next) = > {console.log (1) next () console.log (1.1)}) middleware.push ((next) = > {console.log (2) next () console.log (2.1)}) middleware.push (() = > {console.log (3)}) let fn = compose (middleware) fn ()

When we try to execute fn, it will call the function in the middleware and pass the next function as an argument to each small function.

If we execute next in a small function, we will call the next function of that function in the middleware. And if you don't execute it next, the program won't crash.

After executing the above code, we get the following result:

1232.11.1

So how do we write a compose function to do this?

First, the compose function must return a composed function, so we can write the following code:

Function compose (middleware) {return function () {}}

Then, in the returned function, the first function of the middleware begins to execute. We will also pass the next function as its argument. So let's write something like this:

Function compose (middleware) {

Function compose (middleware) {return function () {let F1 = middleware [0] F1 (function next () {})}}

The next function acts as a switch to continue running in the middleware, as follows:

Function compose (middleware) {return function () {let F1 = middleware [0] F1 (function next () {let f2 = middleware [1] f2 (function next () {...})})}}

Then continue to call the third function in the next function. Wait, this looks like recursion! Therefore, we can write a recursive function to complete this nested call:

Function compose (middleware) {return function () {dispatch (0) function dispatch (I) {const fn = middleware [I] if (! fn) return null fn (function next () {dispatch (I + 1)})}

Okay, this is our writing feature, so let's test it:

Well, this feature can do exactly what it needs. But we can also optimize our compose function to support asynchronous functions. We can improve the following code:

Function compose (middleware) {return async function () {await dispatch (0) function async dispatch (I) {const fn = middleware [I] if (! fn) return null await fn (function next () {dispatch (I + 1)})}

In fact, the above authoring functions are the core mechanism of the well-known node framework koa.

When I choose a candidate, I accept that he or she is not familiar with certain frameworks. After all, there are so many libraries and frameworks in the JavaScript ecosystem that no one can fully master them. But I do want candidates to know these important raw JavaScript techniques, because they are the basis of all libraries and frameworks.

After reading the above, do you have any further understanding of the four problems that can detect your JavaScript level? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report