xTable of Contents [1] Default binding [2] implicit binding [3] implicit loss [4] explicit binding [5]new binding [6] strict mode before
If you want to ask which two knowledge points in JavaScript are easily confused, the scope query and this mechanism are definitely among the top ones. The previous scope series has described the scope knowledge in detail. This series begins with the introduction of another large mountain range--this mechanism for JavaScript. This article is the 4 binding rules for the first--this of the series
Default bindings
In the global environment, this is bound to window by default
Console.log ( this = = = window); // true
When the function is called independently, this is bound to the window by default
function foo () { Console.log (this = = = //true
When the nested function is called independently, this is bound to the window by default
// Although the test () function is nested in the Obj.foo () function, the test () function is called independently, not a method call. So this is bound to windowvar a = 0 by default; var obj = { 2, foo:function() { function Test () { Console.log (this. a); } Test ();} } Obj.foo (); // 0
"Iife"
Iife immediately executes a function that is actually called directly after the function declaration executes
var a = 0; function foo () { (function Test () { Console.log (this. a); }) ()}; var obj = { 2, Foo:foo}obj.foo (); // 0
// equivalent to the above example
var a = 0; var obj = { a:2, foo:function() { function Test () { Console.log ( This. a); } test (); }}obj.foo ();//0
"Closures"
Similarly, the test () function is a standalone call, not a method call, so this is bound to window by default
[note] There are 4 ways to call the function, the function calls the relevant content to this point
var a = 0; function foo () { function Test () { Console.log (this. a); } return test;}; var obj = { 2, Foo:foo}obj.foo () (); // 0
Implicit binding
In general, when called by a function that is contained by a direct object, also called a method call, this is implicitly bound to the direct object
function foo () { Console.log (this. a);}; var obj1 = { A:1, foo:foo, obj2:{ A:2, Foo:foo }} The direct object of the//Foo () function is obj1,this implicitly bound to Obj1Obj1.foo (); // 1 // the direct object of the Foo () function is that obj2,this is implicitly bound to Obj2Obj1.obj2.foo (); // 2
Implicit loss
Implicit loss means that a function that is implicitly bound loses the bound object, and thus binds to the window by default. The situation is error-prone but common.
"Function alias"
var a = 0; function Foo () {console.log ( this .A);}; var obj = {a: 2, Foo:foo} // The Obj.foo is given an alias bar, resulting in implicit loss, because only the Foo () function is assigned to bar, and bar is irrelevant to the Obj object var bar =< Span style= "color: #000000;" > Obj.foo;bar (); // 0
// equivalent to var a = 0; var function foo () { Console.log (this. a);} Bar (); // 0
"Parameter Passing"
var a = 0; function Foo () {console.log ( this .A);}; function Bar (FN) {fn ();} var obj = {a: 2, Foo:foo} // When Obj.foo is passed as a parameter to the bar function, there is an implicit function assignment Fn=obj.foo. Similar to the example above, only the Foo function is assigned to FN, and the FN and obj objects have no relation to bar (Obj.foo); // 0
// equivalent to var a = 0; function Bar (FN) { fn ();} Bar (function foo () { Console.log (this. a);});
"Built-in functions"
Built-in functions are similar to the previous example, and can also cause an implicit loss
var a = 0; function foo () { Console.log (this. a);}; var obj = { 2, foo:foo}settimeout (Obj.foo,+); 0
// equivalent to var a = 0; setTimeout (function foo () { Console.log (this . a);},100); // 0
Explicit binding
Binding an object to this by means of the call (), apply (), bind () method is called explicit binding. For the called function, it is called an indirect call.
var a = 0; function foo () { Console.log (this. a);} var obj = { A:2};foo (); // 0foo.call (obj); // 2
Normal explicit binding does not solve implicit loss problems
var a = 0; function foo () { Console.log (this. a);} var obj1 = { A:1}; var obj2 = { A:2};foo.call (obj1); // 1foo.call (OBJ2); // 2
"Hard bind"
Hard binding is a variant of explicit binding, so this can no longer be modified
var a = 0; function foo () { Console.log (this. a);} var obj = { A:2}; var function () { foo.call (obj);} // manually call Foo.call (obj) inside the bar function. Therefore, regardless of how the function bar is called later, it will always manually raise the Foobar () on obj; // 2setTimeout (bar,100); // 2bar.call (window); // 2
"API"
There are many new built-in functions in JavaScript with explicit binding capabilities, such as 5 iterative methods for arrays: Map (), ForEach (), filter (), some (), every ()
var id = ' window '; function foo (EL) { console.log (el,this. id);} var obj = { ' fn '};[ 1,2,3].foreach (foo); // 1 "Window" 2 "Window" 3 " window" [1,2,3].foreach (Foo,obj); // 1 "FN" 2 "FN" 3 "FN "
New binding
If a function or method call is preceded by the keyword new, it constitutes a constructor call. For this binding, called the new binding
The "1" constructor typically does not use the return keyword, which typically initializes the new object, which is explicitly returned when the function body of the constructor finishes executing. In this case, the result of the constructor call expression is the value of the new object
function fn () { this. A = 2;} var New fn (); Console.log (test); // {a:2}
"2" If the constructor uses a return statement but does not specify a return value, or returns a raw value, the return value is ignored and the new object is used as the result of the call
function fn () { this. A = 2; return ;} var New fn (); Console.log (test); // {a:2}
"3" If the constructor explicitly returns an object using the return statement, the value of the invocation expression is the object
var obj = {a:1}; function fn () { this. A = 2; return obj;} var New fn (); Console.log (test); // {a:1}
[note] Although sometimes the constructor looks like a method call, it will still use this new object as this. In other words, in the expression new O.M (), this is not an O
var o = { function() { returnthis; }} var New = = = O); // {} falseConsole.log (obj.constructor = = = O.M); // true
Strict mode
"1" in strict mode, the this point of the function that is called independently undefined
function fn () { ' use strict '; Console.log (this); // undefined }fn (); function fn () { console.log (this); window}fn ();
"2" in non-strict mode, when you use the call () or apply () method of a function, null or undefined values are converted to global objects. In strict mode, the this value of the function is always the specified value
var color = ' Red ' ; function Displaycolor () {console.log ( this .color);} Displaycolor.call ( null ); // red var color = ' Red ' ; function Displaycolor () { ' use strict ' this .color);} Displaycolor.call ( null ); // typeerror:cannot Read property ' color ' of NULL
At last
The four binding rules for this are: default binding, implicit binding, explicit binding, and new binding, corresponding to the four invocation modes of the function: stand-alone invocation, method invocation, indirect call, and constructor call.
It is not difficult to distinguish these four kinds of binding rules, it is troublesome to develop eyes, to identify the situation of implicit loss
Ultimately, the reason JavaScript is so complicated is because the function is too powerful. Because the function is an object, the prototype chain is more complex, because the function can be passed as a value, so the execution of the environment stack is more complex;
Only understanding the function is understood by JavaScript
Above
In-depth understanding of the 4 binding rules of the first--this of this mechanism series