Who calls this only wants who?
In most cases this points to the caller, as in the following code:
var obj = {
say: function () {
console.log(this)
}
}
obj.say(); // obj
// Variables declared in the global scope can be called with window.say() by default
// This also refers to the window in some global functions, such as setTimeout, etc
var say = obj.say;
say(); // window
Copy the code
Why do I say most of the time? Because this case does not include showing bindings, what about showing bindings? Apply, bind, call
var obj = {
name: 'Joe'.say: function () {
console.log(this.name)
}
}
var obj2 = {
name: 'bill'
}
obj.say.call(obj2) / / li si
Copy the code
Here we use call to force obj. Say’s this to refer to obj2.
This new binding
New is the javascript operator used to create an object. Of course, this is not accurate
function Foo() {
this.name = 'Joe'
this,say = function () {
console.log(this.name)
}
}
var foo = new Foo()
foo.say(); // 'Zhang SAN'
Copy the code
So what happens internally when we use new? The internal mechanism is as follows
function Foo() {
// Create a temporary variable this internally
this = {
// Then add all the properties of this. XXX under Foo to this
name: 'Joe'.say: function () {
console.log(this.name)
}
}
// After the property is mounted, return this
return this
//
this.name = 'Joe'
this,say = function () {
console.log(this.name)
}
}
Copy the code
The above operation is the internal operation when we use new. That’s why the bind binding doesn’t work when we use the function that bind returns for new, because the function creates this internally when new, making the explicit binding invalid, right
Priority problem
Priority here refers to the priority of explicit and implicit binding, new and implicit binding. Explicit binding is bind, apply, call, etc., and implicit binding is obj. XXX, etc
function foo() {
console.log(this.a)
}
var obj1 = {
a: 2.foo: foo
}
var obj2 = {
a: 3.foo: foo
}
obj1.foo(); / / 2
obj2.foo(); / / 3
obj.foo.call(obj2); / / 3
obj.foo.call(obj1); / / 2
Copy the code
As you can see, the display binding has a higher priority. Let’s figure out who has the highest priority for new binding versus implicit binding.
function foo (something) {
this.a = something
}
var ob1 = {
foo: foo
}
var obj2 = {}
obj1.foo(2);
console.log(obj1.a); / / 2
obj1.foo.call(obj2, 3);
console.log(obj.a); / / 3
var bar = new obj1.foo(4);
console.log(obj1.a); / / 2
console.log(bar.a); / / 4
Copy the code
From the above we can see that the new binding takes precedence over the implicit binding. From the above conclusion, we can conclude the order of priority: new binding > explicit binding > implicit binding
To determine this
Now we can determine which rule is applied to a function at a particular call location based on priority.
- Is the function called in new (new binding)? If so, this is the newly created object.
var bar = new foo()
- Are functions explicitly bound by call, apply, bind, and so on? If so, this points to the bound object.
var bar = foo.call(obj2)
- Is the function called in a context (implicit binding)? If so, this points to the binding context object.
var bar1 = obj1.foo(); var bar2 = obj.foo; bar2() Copy the code
- If neither, use the default binding. If in strict mode, bind to undefined, otherwise bind to global objects.
var bar1 = foo() "use strict" var bar2 = foo() Copy the code
Binding exception – arrow functions
Arrow functions are es6 functions with special rules that use the operator => called the fat arrow. Instead of using the four standard rules for this, arrow functions determine this based on the outer (function or global) scope.
function foo () {
return a= > console.log(this.a)
}
var obj1 = {
a: 2
}
var obj2 = {
a: 3
}
var bar = foo.call(obj1);
bar.call(obj2); // 2, not 3
Copy the code
The arrow function created inside foo() captures foo() ‘s this at the time of the call. Since foo was originally called to obj1, the newly returned function’s this points to obj1 unchanged, and the binding of the arrow function cannot be changed by call or apply (new does not work either). This is most commonly used in callback functions, such as event handlers or timers:
var a = 3
function foo () {
setTimeout((a)= > console.log(this.a), 100)}var obj2 = {
a: 1
}
foo.call(obj); / / 2
foo(); / / 3
Copy the code
As you can see from the above code, the rule for this in the arrow function is: This in the arrow function refers to this when the function is executed