define

  1. 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

  2. It’s determined at run time, they just careWhere to call fromDynamic scope is based onThe call stackRather thanGenerated when writing codeThe scope is nested, focusing only on where it is called

This is in normal functionsfunction xx (){}

  1. This does not in any case refer to the lexical scope of the function

  2. 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.applybind

  1. 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.)

newThe binding

When a function is called with new, or when a constructor call occurs, the following operations are performed automatically.

  1. Create (or construct) a brand new object.
  2. The new object will be connected by the implementation [[prototype]].
  3. This new object is bound to the function call’s this.
  4. 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.