Recently, some people in the group often raise some simple questions, such as sending a piece of code that is messy and then talking about a variable in it. For example, here is a good example:
Function fn (arg ){
Alert (this. arg );
Alert (this );
}
Fn (123 );
Var o = {fn: fn };
O. fn (123 );
Then there may be such a problem:
Why is this. arg undefined? Why is this different when fn is called twice?
To this end, I feel that as an immature front-end, I should still give my advice on what I can do. Therefore, in this article, we plan to explain how Object Search in javascript is performed on a very superficial level.
Note: This article only introduces the process of searching for this behavior from the appearance. The points in this article are not all correct, and there are even some errors, however, this is also intended for beginners to better understand the object search process. I believe that if it is too abstract and in-depth, it will lead to some negative effects. If one day you come back and find that this article is not so correct, congratulations, you can find the correct way forward at that time, the errors in this article will not affect you any more.
Object category
The so-called Object Search refers to finding an object that is currently needed within the scope of a piece of executable code. In javascript, the objects to be searched can be roughly divided into three types:
Search for variables, such as foo ++. Here we will look for a variable named foo.
Search for attributes, such as foo. bar ++. Here, we will look for an attribute named bar under the foo variable.
This search refers to the processing of the this keyword.
To distinguish between the three types of Object Search is the first task to be completed. You can determine based on the following principles:
Variables are only composed of variable names, namely, individual foo and bar.
The attribute is always accessed in two forms, namely foo. bar and foo [bar]. Therefore, if "." or "[]" is displayed, it can be regarded as an attribute query.
Needless to say, this is a good keyword.
Take a look at this Code:
Var foo = this;
Foo. bar ();
The two lines of code reflect three types of object searches:
Search for this object and assign it to the foo variable.
View the foo variable.
Search for the bar attribute under the foo variable and call it as a function.
Variable Search
After finding an object as a variable, you can view it according to the Variable Search rules.
Variable Search: searches on the scope chain. The scope chain is one of the two very famous javascript chains. The following code reflects a standard scope chain:
Var foo = 1;
Function (){
Var bar = 2;
Function B (){
Foo = 3;
Function c (){
Alert (foo +, + bar); // pay attention to this line
}
C ();
}
B ();
}
A ();
In the c function, two variables are searched, foo and bar, respectively.
Variable Search can simply follow the principle of "from bottom to top", that is:
Search for foo and bar in the range of Function c. Obviously, there is no declaration of foo and bar in Function c, and the search fails.
Search for foo and bar in the function that contains c, that is, function B. It can be seen that only the values assigned to foo in function B are not declared, and the search fails.
Find foo and bar in the range of function a including function B, and find the bar declaration. Therefore, the bar is determined to be 2.
Because a is not included by any function, it searches for foo in the global scope and finds that there is a foo declaration. Therefore, it is determined that the value of foo is 1. But in function B, there is a value assigned to this foo, so the value of foo is changed to 3.
After confirming that the foo value is 3 and the bar value is 2, the output is "3, 2 ".
To sum up, the search for variables is extended by the scope chain. The scope chain can be simply seen as the inclusion relationship between functions. When a variable does not exist in the contained function, search for the function that contains it until the global scope.
Attribute search
After you confirm that an object is queried as a property, you can view it according to the property search rules.
Property search: searches on the prototype chain. The prototype chain is another one of the javascript double links. The following shows a prototype chain:
Var a = function (){};
Var B = function (){};
Var c = function (){};
B. prototype = new ();
C. prototype = new B ();
A. prototype. foo = 1;
B. prototype. bar = 2;
C. prototype. foo = 3;
Var o = new c ();
Alert (o. foo +, + o. bar); // search for this row
Attribute search is a process of constantly searching for prototype, namely:
Check whether foo and bar are defined in c. prototype. If foo is defined, the value is 3.
If c. prototype is the object obtained by new B (), check whether bar is defined in B. prototype and the value is 2.
Therefore, it is determined that the foo value is 3, the bar value is 2, and the output is "3, 2 ".
To sum up, the property search process is extended by the prototype chain. The specific knowledge of the prototype chain is not described in detail here. You can refer to another article for reference. For all objects, the prototype chain will eventually be Object. prototype.
This search
This search is a bit confusing for many people, and it seems that many people think that this is unstable. It is really speechless. This search can be said to be the simplest of the three types of Object Search, because in fact, the determination of this object does not have a "Search" process.
First, this object only needs to be determined in a function. If it is a Global object in the whole local area, this is usually a window object in the browser. In javascript, there are four methods to call a function:
Function Invocation Pattern
For example, the call form of 'foo () 'is called Function Invocation Pattern, which is the most direct form of use of the Function. Note that foo appears as a separate variable rather than a property.
In this mode, this in the foo function is always a Global object, and it is a window object in the browser.
Method Invocation Pattern
Such as 'foo. the call form of bar () is called Method Invocation Pattern. Note that the called function appears as an object attribute, and ". "or.
In this mode, this in the bar function is always the object before "." or "[". In the above example, it must be the foo object.
Constructor Pattern
The call in the form of 'new foo () 'is called Constructor Pattern. The keyword 'new' is very easy to identify.
In this mode, this inside the foo function is always the object returned by new foo.
Apply Pattern
'Foo. call (thisObject) 'and 'foo. apply (thisObject)' are called Apply Pattern. They use the built-in 'call' and 'application' functions.
In this mode, the first parameter of 'call' and 'application' is this in the foo function. If thisObject is 'null' or 'undefined', it will become a Global object.
The above four methods are used to determine the Pattern used by a function, so that you can easily determine what this is.
In addition, this will never extend the scope chain or the prototype chain to show a "Search" process. It will only be fully confirmed during function calls.
Summary
Search for an object:
Determine whether to search for variables, properties, or this.
If it is a variable search, the extended scope chain is located. If it cannot be found, it is a ReferenceError.
For attribute search, the prototype chain is extended and undefined is used to locate the link.
For this search, find the code that calls the function and determine what this is based on the call form.
Note that you can split a search process, such as this. foo. bar. yahoo (), into code like this to make it clearer:
Var o = this; // this search
Var foo = o. this; // search for Attributes
Var bar = foo. bar; // search for Attributes
Bar. yahoo (); // query the attributes and add Method Invocation Pattern.
Finally, if one day you can understand these things, this article will not be very useful to your users:
Why can't ReferenceError be found in extended scope.
In fact, variables are also attributes of a special object.
This may not be Global, or undefined.