For a long time, I’ve thought of scope as context, which makes understanding this in JavaScript a lot of trouble, so the first thing I want to say at the beginning of this article is that scope and context are not the same thing. Scope refers to the accessibility of a variable, and context determines this. (Note that execution context refers to scope, which is the JavaScipt specification, so follow it)
There are only two types of scope in JavaScript. One is global scope and the other is function scope. The context is related to this, which is bound at runtime, and its context depends on where the function is called. The binding to this has nothing to do with where the function is declared.
When a function is called, an activity record (that is, the execution context) is created. This activity contains information about where the function was called, how the function was called, and what parameters were passed in. This is one of the recorded properties that will be used during the execution of the function.
Of course, this quote comes from “JavaScript You Don’t Know (Volume 1),” which is highly recommended here.
Again, this actually binds when the function is called, and what it points to depends entirely on where the function is called.
The position
Let’s take a look at what types of function calls are included. Only when you know where the function is called can you understand the point of this correctly.
Default binding (global call)
var a = 2;
function foo() {
console.log(this.a)
}
foo();
Copy the code
That’s the default binding, and the function foo is called directly.
Implicit binding
b = 2;
var obj = {
b: 3.foo: foo
}
function foo () {
console.log(this.b);
}
obj.foo(); / / 3
Copy the code
The reason why this is called implicit is that the foo function, whether declared inside or outside of obj, does not belong to the object obj (obj only refers to the value of foo), but this is bound to the object’s context when executed. Of course, if there are multiple object chaining calls, this will only be bound to the last layer. Obj2.obj1.foo (), this is bound to obj1 in the object context.
There’s a catch, of course
var obj = {
b: 3.foo: foo
}
function foo () {
console.log(this.b);
}
var bar = obj.foo;
bar(); / / 2
Copy the code
Here bar is a direct reference to foo, which is equivalent to var bar = obj. Foo = foo
console.log(bar === foo && foo === obj.foo && bar === obj.foo) // true
Copy the code
So just like the first default binding, the bar function is called directly in the global context, so this points to the global.
Another is nested functions
b = 2;
var obj = {
b: 3.foo: foo
}
function foo () {
console.log('foo'.this.b);/ / 3
foo2();
}
function foo2() {
console.log('foo2'.this.b); / / 2
}
obj.foo();
Copy the code
In fact, foo2 is called directly by (window).
Show binding call, apply, bind
The call, apply, and bind functions can force a function to be called from which object (or context)
b = 2;
var obj = {
b: 3,
foo: foo
}
function foo () {
console.log('foo', this.b); } foo.call(obj); / / 3Copy the code
Of course, if you pass in a value of a primitive type, JavaScript will convert it to its object form.
The new binding
Speaking of the new operator, we have to talk about its inner workings, what we actually do when we execute the new operation.
[[prototype]] = fun.prototye [[prototype]] = fun.prototye If the function returns no other object, then it returns the newly created object return obj;
So the new binding is still an explicit binding.
To sum up, we can make judgments in the following order
1 Whether the function is called in new (new binding) and returns a new object if it is bound to this. 2 Whether the function is called by call, apply (explicit binding) if it is bound to that specified object. 3 Whether the function is called in a context object (implicit binding). This binds to the context-free grammar object. 4 If neither of these is the default binding. This binds to the global object or undefined (strict mode).
exception
There is an exception to this rule. If you pass null or undefined to call, apply, or bind as a binding to this, these values will actually be ignored and the default binding will be used. So when do we bind to null or undefined? One is to use apply to expand an array, which is certainly useful (but it does appear in ES6… Operator to expand the array.
function foo(a, b) {return a + b}
foo.apply(null[2.3]);
Copy the code
The arrow function, the “this” in the arrow function is determined by the outer scope, which means that the “this” in the arrow function depends on where the arrow function is declared.
a = 2;
var obj = {
a: 3.foo: foo
}
function foo () {
return (a)= > {
console.log(this.a);
};
}
var fun = foo.call(obj);
fun(); // 3 The outer scope of the arrow function is foo, and this of foo is bound to the obj object
Copy the code
a = 2;
var obj = {
a: 3,
foo: foo
}
var arrowFun = () => {
console.log(this.a);
}
function foo () {
returnarrowFun; } var fun = foo.call(obj); fun(); //2 The outer scope of the arrow function is the global scope, and this in the global scope points to the global contextCopy the code
The last
Finally welcome everyone to pay attention to my personal blog, there will be more wonderful documents, like words can also give a star.
Making a link
DJL Xiao’s blog