This is detailed in JavaScript

Source: Internet
Author: User

This is a must for every person who wants to learn JavaScript in depth, I have read a lot of books for this, although I have a certain understanding of this and often use this, but if someone asked me this is what ah? I still can't give someone a perfect explanation. Recently a small opportunity, let me re-understand this, and finally feel that I can recognize the this will give others to listen to, so now can't wait to share my understanding

Speaking of this, the most important thing is this point (this is not accurate, because this is just a property of the active object created when the function is called).

Some people may think this is pointing to itself, because this is the meaning of this word, but this understanding should be wrong, do not believe? Look at the code

1 functionfoo (num) {2Console.log ("foo" +num);3      this. count++;4 }5Foo.count = 0;6  for(vari = 0; I < 5; i++) {7 Foo (i);8 }9 Console.log (foo.count);TenConsole.log (count);

For the output of the second line, we're sure everyone knows the Answer.

1 Foo0 2 foo1 3 Foo2 4 Foo3 5 Foo4

So what's the output of line nineth? (if this points to itself, Foo is called 5 times Foo.count should be 5, but!) )

In fact, This.count does not have the + + to explain that this is not pointing to itself. here, This executes the global variable window

Someone will say, I know he is not pointing to himself, he is clearly pointing to the scope of it (well, for a long time I think so too). But in fact this is not true, still, we use a piece of code to prove

1 function foo () {2     var a = 2; 3      this . Bar (); 4 }5function  bar () {6     console.log ( this . a); 7 }8 foo ();

What is the output from line sixth of this code? Is it 2?

Operation result is undefined

This does not point to its own scope. now you must be tyrannical to know what the hell this is, and now we're going to start with a layer of parsing.

To know how the function binds this during execution, first know where the function is Called. Maybe a lot of people can easily find the function call location, it is easy to look at my code and you come up with the answer is not the same

1 functionBaz () {2     //Current call stack: Baz3    //The calling location is global scope4Console.log ("baz");5Bar ();//where bar is called6 }7 functionBar () {8     //Current call stack: Baz bar9    //The call location is in BazTenConsole.log ("bar"); oneFoo ();//the call location of Foo a } - functionfoo () { -     //Current call Stack: Baz-bar-foo the    //The call location is in bar -Console.log ("foo"); - } -Baz ();//Baz the call location

Take a look at the above code, from Baz (); start, Baz in the global, then Baz call Bar (); So Bar's call position is in baz, and then bar calls Foo (); The call location of Foo is in BAZ. The Execute Foo function is the call stack baz, bar--foo.

By calling the function to find the call stack, we can find out the real call location of the function, but if the code is too large it might be easy to make mistakes, so we have a better way

The right-pointing arrow slides past the call stack that the Foo function executes, and the second element in the stack is the real call Location.

After finding the call location, let's take a look at what binding rule the binding of this matches

1. Implicit binding : see if the call location has a context object, i.e. whether it is owned or contained by an object (the inclusion is not wrapped up in curly braces).

 1  var  a = 3  2  function   Foo () { 3  console.log (this  .a);  4  }  5  var  obj = { 6  a:2 7   Foo:foo  8  };  9  obj.foo (); 

The above is a function call inside the output this point to a value, do not say the answer, first look, this code and the above indicates that this is not a point to the scope of the code of the difference is what, I think we all found that the Foo function call is Obj.foo (). The Foo function is invoked as a method of the obj Object. obviously, according to the location of the Foo function, he does not belong to the obj object, but ~ ~ haha, said a lot of back but the ~~foo function is called by the context of obj to refer to the function, that is, his base point is the obj object, that is, his this is also pointing to his context Object. Such an analysis, the answer is obvious, THIS.A equivalent to OBJ.A is 2.

(ps: if the reference to an object property is multi-layered, only the last layer affects the call location).

2. Explicit binding :

The implicit binding above is to bind this implicitly to this object by invoking the property of the function bound in an Object.  So showing bindings is a way of forcing a function to be bound on an object, which is called (...). Apply (...) These two methods work in a similar way, so we use call () as an example to analyze their work process.

The first parameter of these two methods is an object, and the this of the bound function binds to the object, looking at a piece of code

1 function foo () {2     console.log (this. a); 3 }4var obj = {5     a:26}; 7 Foo.call (obj);

The Foo function executes with the call function, and the first parameter of the called function is the obj object, and the This property of the Foo Function's active object is bound to the obj object, so output 2.

3.new Bindings

1 function Foo (a) {2    This. a = a; 3 }4varnew Foo (2); 5 Console.log (bar.a);

Use new to invoke the function, that is, when a constructor call occurs, the following actions are performed

    1. Create an entirely new object
    2. This object will be executed by the [__proto__] link (bar.__proto__=foo.prototype)
    3. This new object is bound to this on the function call
    4. If the function does not return a different object, the function call in the new expression will automatically return the object

When the Foo function is executed using the new operator, a completely new object is created and assigned to the variable bar. After the prototype link (this is not the scope of our discussion today) the This property of the Foo function activity object is bound to the newly created object bar, and the Foo function does not return a value, so the bar object created by new is automatically Returned.

4. Default binding default binding is a default rule that does not conform to any of the above rules

1 function foo () {2     console.log (this. a); 3 }4var a = 2; 5 foo ();

The above code foo function is directly used without any adornments and does not conform to any one of the binding rules in 1-3, so only the default binding rules are used, and the default binding rules are bound to the global object in non-strict mode (the call location of the Foo function is undefined in strict mode).

well, the four binding rules for this are already explained. Is there an unexpected situation?

is not an unexpected situation depends on your understanding of this has not been in place, there is no serious analysis, the following two special circumstances let everyone turn the brain

1 functionfoo () {2Console.log ( this. a);3 }4 varobj = {5A:2,6 Foo:foo7 };8 varBar =obj.foo;9 varA = "Global";TenBar ();

The only special point of this code is that bar refers to the Foo function of obj. And the answer becomes GLOBAL. What is this for?

first, Let's just output bar.

You can see that bar is an alias for the Foo () function, although he is the Foo () function referenced by obj, but he simply refers to the Foo function and does not refer to the execution context of the obj object, so he conforms to the fourth default binding of the This rule Above. So this is pointing to global output globally.

1 functionfoo () {2Console.log ( this. a);3 }4 functiontoDo (fn) {5 fn ();6 }7 varobj = {8A:2,9 Foo:fooTen }; one varA = "Global"; aToDo (obj.foo);

This code is an incoming callback Function. In the Todo function, the transfer of FN is still just the function of foo, and does not pass the execution context of the obj object, so there is no special binding at the position of the FN () call, which conforms to the default binding of this rule, which points to the Global. Don't believe me? We're going to output fn in the TODO function to see if it's the Foo Function.

It seems that I am right.

After everything has been solved you must ask again, what if the function that I meet all of a sudden meets the two rules? Uh... Let's take a look at the precedence of binding rules.

Needless to say, the default binding has the lowest priority, so don't worry about it first, just look at the implicit binding and show the binding who has higher priority

1 functionfoo () {2Console.log ( this. a);3 }4 varObj1 = {5A:2,6 Foo:foo7 };8 varObj2 = {9A:3,Ten Foo:foo one }; a Obj1.foo (); - Obj2.foo (); -   the Obj1.foo.call (obj2); -Obj2.foo.call (obj1);

It seems that explicit binding easily overcomes implicit binding, and whose precedence is higher for explicit binding and new? well, because new and call (), apply () cannot be used at the same time, so I did not write the test code between them, but after checking the information, the conclusion is that the new priority is higher than the explicit binding (the great God can give a new priority higher than the actual binding Example) ~ if any, please put in a comment , the Little woman thanked ~ ~).

That concludes the experience is to judge the this binding rule, first look at new, and then see the explicit binding, and then see the implicit binding, none of the default bindings are Used.

however, There are exceptions to everything, and it is not possible to make a definitive conclusion, for example, if an explicit binding is an object passing in null or undefined, then call or apply will be ignored for the default binding.

There are many other exceptions waiting for us to find Out. however, the general situation occupies a majority, so as long as the correct search for analysis function call stack, find the function call location, in the function call location to judge the use of that binding rules, the basic can correctly determine the point of this.

And look at some special uses.

1 functionperson ()2 {3    this. username= "huangwei";4    this. sayhello=function(){5Console.log ("username:" + this. username);6   }7Console.log ( this);8   return  this;9 }Ten   one varperson=Newperson (); a Person.sayhello (); -Console.log (person);

Comment out line eighth (return This) and execute the same result.

Reference: http://www.cnblogs.com/xiaoruo/p/4492453.html

http://gejiawen.github.io/2015/03/18/Javascript/%E5%8C%BA%E5%88%86JS%E4%B8%AD%E7%9A%84__proto__%E5%92%8Cprototype/

This is detailed in JavaScript

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.