Recently reading an advanced JavaScript book, "You Don't know the JavaScript (roll up)", this time study "this".
When a function is called, an activity record ( execution context ) is created.
This record contains information about where the function was called (the call stack), the calling method of the function, the parameters passed in, and so on.
This is one of the attributes of the record, which is used during the execution of the function.
This does not point to the function itself or to the scope of the function .
This is actually the binding that occurs when a function is called, and what it points to exactly depends on where the function is called .
First, the call location
The call location is in the previous invocation of the currently executing function, and the source is viewed.
function Baz () { //The current call stack is: Baz //So the current call location is the global scope console.log ("Baz"); Bar (); <--Bar Call position}function Bar () { //Current call stack is Baz , bar//So the current call position is Console.log ("Bar") in Baz; Foo (); <--Foo's call position}function foo () { //Current call stack is Baz-bar- -foo///So the current call position is Console.log in bar ("Foo ");} Baz (); <--Baz's call location
Ii. binding Rules
You must find the location of the call and then decide which of the following four rules you want to apply.
1) Default Bindings
The most common type of function call: a standalone function call . You can think of this rule as the default rule when other rules cannot be applied.
function foo () { console.log (THIS.A);} var a = 2;foo (); 2
2) Implicit binding
The rules for implicit binding are whether the call location has a context object , or whether it is owned or contained by an object .
function foo () { console.log (THIS.A);} var obj = { a:2, foo:foo};obj.foo ();//2
But sometimes implicit loss occurs.
function foo () { console.log (THIS.A);} var obj = { a:2, foo:foo};var bar = obj.foo;//function var a = "oops, global";//bar ();//"Oops, global"
Although bar is a reference to Obj.foo, it actually refers to the Foo function itself .
So bar () at this point is actually a function call without any modification, with the default binding applied.
3) Explicit binding
Call (..) using a function and apply (..) Method.
function foo () { console.log (THIS.A);} var obj = { a:2};foo.call (obj);//2
The Bind method is often seen in many libraries, which is a hard binding , an explicit forced binding, and the following is a bind implementation.
function foo (something) { console.log (THIS.A, something); return THIS.A + something;} Simple auxiliary bind function functions bind (FN, obj) { return function () { return fn.apply (obj, arguments); };} var obj = { A:2};var bar = bind (foo, obj); var b = bar (3);//2 3console.log (b);//5
4) New Binding
Using new to invoke a function, or when a constructor call occurs, the following actions are performed automatically:
1. Create (or construct) an entirely new object.
2. This new object will be executed [[prototype]] connected.
3. This new object is bound to this of the function call.
4. If the function does not return another object, the function call in the new expression will automatically return the new object.
function foo (a) { this.a = A;} var bar = new Foo (2); Console.log (BAR.A); 2
Third, priority
The default binding priority is the lowest of the four rules.
1) Explicit binding precedence is higher than implicit binding
function foo () { console.log (THIS.A);} var obj1 = { a:2, foo:foo};var obj2 = { A:3, foo:foo};obj1.foo ();//2 Obj2.foo ();//3obj1.foo.call (OBJ2); 3 Obj2.foo.call (OBJ1); 2
2) The new binding has a higher precedence than an implicit binding
function foo (something) { this.a = something;} var obj1 = { Foo:foo};obj1.foo (2); Console.log (obj1.a);//2var bar = new Obj1.foo (4); Console.log (obj1.a);//2 Consol E.log (BAR.A); 4
3) The new binding modifies the display binding in this
function bind (FN, obj) { return function () { return fn.apply (obj, arguments); } function foo (something) { this.a = something;} var obj1 = {};var bar = Foo.bind (obj1);//bar is hard bound to obj1 on bar (2); console. Log (obj1.a); 2 var baz = new bar (3); Console.log (obj1.a); Did not change the obj1.a to 3, or 2 console.log (BAZ.A); 3
4) Judging this
1. Is the function called in new (new binding)? If so, this binds to the newly created object.
var bar = new Foo ()
2. Is the function called by call, apply (explicit binding), or hard bind? If so, this binds to the specified object.
var bar = Foo.call (OBJ2)
3. Is the function called (implicitly bound) in a context object? If so, this binds to the context object.
var bar = Obj1.foo ()
4. If not, use the default bindings. If in strict mode, bind to undefined, otherwise bind to the global object.
var bar = foo ()
Iv. Binding Exceptions
1) The This is ignored
If you pass null or undefined as this binding object to call, apply, or bind.
These values are ignored on invocation and are actually applied by default binding rules.
function foo () { console.log (THIS.A);} var a = 2;foo.call (null); 2
2) Indirect reference
It is possible (intentionally or unintentionally) to create an "indirect reference" to a function.
In this case, calling this function will apply the default binding rule.
function foo () { console.log (THIS.A);} var a = 2; var o = {a:3, foo:foo}; var p = {A:4}; O.foo (); 3 (P.foo = O.foo) (); 2
Assignment expression P.foo = The return value of O.foo is a reference to the target function, so the call location is foo () instead of P.foo () or O.foo ().
3) Soft Binding
If you can assign a default binding to a global object and a value other than undefined.
It is possible to implement the same effect as hard binding, while preserving implicit binding or explicitly binding the ability to modify this.
It is possible to achieve the effect we want by means of a method called soft binding .
Function.prototype.softBind = function (obj) { var fn = this; Capture all curried parameters var curried = [].slice.call (arguments, 1); var bound = function () { return fn.apply ((!this | | this = = (Window | | global))? Obj:this, curried.concat.apply (cur ried, arguments); }; Bound.prototype = Object.create (fn.prototype); return bound;};
function foo () { console.log ("Name:" + this.name);} var obj = {name: "obj"}, obj2 = {name: "Obj2"}, obj3 = {name: "Obj3"}; var fooobj = Foo.softbind (obj); foo OBJ (); Name:obj <----applied soft bind obj2.foo = Foo.softbind (obj); Obj2.foo (); Name:obj2 Fooobj.call (OBJ3); Name:obj3settimeout (Obj2.foo);//Name:obj <----soft binding applied
The soft-bound version of Foo () can manually bind this to Obj2 or obj3.
However, if the default binding is applied, this is bound to obj.
The javascript you don't Know (ii)--this