define
-
To be clear, JavaScript doesn’t actually have dynamic scope. It has lexical scope and is straightforward. But this mechanism is somewhat like dynamic scope
- It’s determined at run time, they just care
Where to call from
Dynamic scope is based onThe call stack
Rather thanGenerated when writing code
The scope is nested, focusing only on where it is called
This is in normal functionsfunction xx (){}
-
This does not in any case refer to the lexical scope of the function
-
The binding of this has nothing to do with the position of the function declaration, except how the function is called. When a function is called, an active record (sometimes called the execution context) is created. This record contains information about where the function was called (call stack), how the function was called, the parameters passed in, and so on. This is one of the properties of the record that is used during the execution of the function.
The position
Understanding dynamic scope, or this, is impossible to avoid understanding the call location, and the most important thing is to analyze the call stack (that is, all the functions called to get to the current execution location). The call location we care about is in the previous call to the currently executing function. Example:
function baz(){
// The current call stack is: baz, equivalent to window->baz
// Therefore the current call location is global scope
bar();
}
function bar() {
// The current call stack is window->baz->bar, the call location is always the second element in the stack
// Therefore, the current call location is console.log("bar") in baz;
foo();//<--foo's call location
}
function foo(){
// The current stack is window->baz->bar->foo
// Therefore, the current call location is in bar
console.log("foo");
}
baz();//<--baz call location
Copy the code
Binding rules
The pointer to the method that contains this is under which scope I am currently calling. Remember this: No matter how confusing this is in your interview, you will be able to tell
The default binding
Example:
function foo(){
console.log(this.a);
}
var a =2;
foo(); / / 2
Copy the code
When foo() is called, this.a is resolved to the global variable a. Why is that? Because in this case, the default binding for this is applied when the function is called, this points to the global object. Why is the default binding used here? By calling location analysis,foo() is called directly with an undecorated function reference. So it can only be called by default
Implicit binding
function foo(){
console.log(this.a);
}
var obj = {
a:2.foo: foo
}
obj.foo(); / / 2
Copy the code
When a function reference has a context object, the implicit binding rule binds this in the function call to that context object. Because this is bound to obj when foo() is called, this.a and obj.a are the same
Only the top or last level of the object property reference chain affects the location of the call (the best way to think about it is to look at which scope the call pointer is in).
The problem with implicit binding: implicit loss
We get confused by this because we get confused by things like xx.xx, but we can understand implicit loss if we understand it in terms of Pointers, so as to remove its fancy ‘coat’.
Example a:function foo(){
console.log(this.a);
}
var obj ={
a:2.foo:foo
};
var bar = obj.foo // Function alias, this is a global bar
var a ='ops! global' // Add an A to the global
bar()// 'ops global'
Copy the code
As you can see from this example, bar refers to obj.foo(the object. Foo pointer, let’s call it *a, points to bar as well as obj.foo), but when we call bar(), This is window.bar(), so this refers to window by default and has nothing to do with obj.foo
We’re looking at a piece of code, trying to analyze it in terms of Pointers
Example b:function foo(){
console.log(this.a)
}
var obj = {
a:2.foo:foo
}
var a = 'oops, global' // A is a global object attribute
setTimeout(obj.foo, 100) // 'oops, global'
Copy the code
This is you don’t know the js code in the book, the book of this code only shows as a result, this was why does not give, then see here is very bad, I don’t understand is my bad points, and then I will try to use the pointer to analysis, the result is a bit… (if there is error analysis, please indicate) :
In example B, we clearly see that setTimeout calls obj.foo, huh? That’s not true. It’s obj. Foo, and based on what I’ve learned this refers to his most recent call, this should refer to foo. Why is the book telling a in global and not a in obj? Here we go!! We were fooled by obJ. Foo, which is a suit of clothing. Whose suit? It’s the clothes of the hands. Which hands? A pointer to foo(). Ok, now instead of calling this pointer obj.foo, we can call it *a, and the setTimeout code in example B is equivalent to setTimeout(*a, 100). So you see why it’s a under window? Who called the pointer *a?? SetTimeout scope, so this in the *a pointer method points to the scope of setTimeout
According to the binding
We can tell js that we want to call this function pointer *a in some scope, i.e. we specify the pointer * A that calls this function
Show binding:call
.apply
和 bind
- Hard binding: Explicitly forced binding
- For example:
function foo(){
console.log(this.a);
}
var obj = {
a:2
}
foo.call(obj); / / 2
Copy the code
I’m forcing your function pointer into the scope of obj
Note: If you pass a primitive value (String, Boolean, or number) as a binding object to this, the primitive value will be converted to its object form (i.e., new String(..)). , new Boolean (..) Or the new Number (..) ). This is often referred to as “boxing”. (Js you didn’t know)
- Typical application scenarios of hard binding
function foo(something){
console.log(this.a, something);
return this.a + something;
}
var obj = {
a:2
}
var bar = function (){
return foo.apply(obj,arguments);
}
var b = bar(3); / / 2, 3;
conosole.log(b); / / 5
Copy the code
- Some built-in functions can provide binding objects, such as forEach(fn, thisArg), thisArg(used as the value of this when the callback is executed.)
new
The binding
When a function is called with new, or when a constructor call occurs, the following operations are performed automatically.
- Create (or construct) a brand new object.
- The new object will be connected by the implementation [[prototype]].
- This new object is bound to the function call’s this.
- If the function returns no other object, the function call in the new expression automatically returns the new object.
priority
New Binding > Explicit Binding > Implicit Binding > Default binding
This is in the arrow function() = > {}
-
In a nutshell, the arrow function behaves completely differently from normal functions when it comes to the this binding. It abandons all the rules of the normal this binding and instead overrides the original value of this with the current lexical scope.
-
The binding of arrow functions cannot be modified (nor new)
-
Arrow functions are most commonly used in callback functions, such as event handlers or timers
Conclusion:
If you want to determine the this binding of a running function, you need to find where the function is called directly. Once found, we can apply the following four rules in sequence to determine the object bound to this.