Preface:
If you have experience developing other languages and don’t have a deep understanding of JavaScript, you might think this is the same…
All right! No matter you are not, the article has written, beg you to see still no 🤣?
Confusing this
Consider the following code:
function say(){
console.log("Hello,world!");
this.count++;
}
say.count = 0;
var count = 0;
for(var i = 0; i <10; i++) say();console.log(say.count);
console.log(count);
Copy the code
In general, we would expect this to refer to the function object that contains it. So this.count should be say.count, not var count, so the final output is 10, 0;
Yet?
Say. count never increases! You can see that this does not always refer to the function itself. There must be some “inside story” waiting for us to uncover!
Careful as you may have noticed,this.count
It points to a global variablecount
, the specification,this
It’s not true. It’s our understanding of it that’s wrong.
Where does this come from?
In fact, this is determined at runtime:
When a function is called, the execution context of the function is created, including this. Execution context. The this binding in the execution context depends on how the function is called; if called by an object, this refers to that object.
Simply put, whoever the function is called by is this.
Where exactly is the location of the call
Are you already cocky? Please accept the beating of good JavaScript!
function hello(){
console.log("Hello,world!");
this.count++;
}
function say(){
hello();
}
say.count = 0;
var count = 0;
for(var i = 0; i <10; i++) say();console.log(say.count);
console.log(count);
Copy the code
“Ah, right here…?” — hello is inside say, so this.count++ is say.count++, not count++.
Yeah, it’s good… What did you guess?!
“You are silly, teach me wrong! You said this depends on where you call it.”
Don’t worry, the call location is actually where the function is called. But this call location is not just the location of the calling function. This explains the call stack:
The call stack is a mechanism by which an interpreter (such as a JavaScript interpreter in a browser) tracks the flow of function execution. When multiple functions are called in the execution environment, this mechanism allows us to track which function is being executed and which function is being called in the body of the executed function.
Look at where hello is called: Hello is accessed directly (without any function objects in between). Therefore, it is still called by the global object, and its execution context is still the global execution context.
That is, if we want this to refer to say, we should use say to access Hello, right? :
function hello(){
console.log("Hello,world!");
this.count++;
}
function say(){
say.helloFun();// say-> helloFun
}
say.helloFun = hello;/ / points to hello
say.count = 0;
var count = 0;
for(var i = 0; i <10; i++) say();console.log(say.count);
console.log(count);
Copy the code
Sure enough, this finally points to say:
It’s time for the ultimate test before we go any further;
function hello(){
console.log("Hello,world!");
this.count++;
}
function say(){
say.helloFun();
}
say.count = 0;
var count = 0;
for(var i = 0; i <10; i++) (say.helloFun = hello)();console.log(say.count);
console.log(count);
Copy the code
Say.count is 10, or is it 0? The answer is at the end.
The binding rule for this
The default binding
Outside of any function, this points to a global object (if the browser is window).
Inside a function, this refers to where the function was called. It is worth noting, however, that in strict mode, if the function is not called by any function, this will remain undefined (it does not point to window by default).
Implicit binding
That is: this depends on the location of the call.
But there are cases where implicit binding is “unbound” — we often want to pass a function object to another function to execute:
However, it did not achieve the desired results. A closer look makes sense: the arguments received by the fun method actually point to the say function without passing through the OBj object.
According to the binding
We would expect the say function in obj to bind only to obj, and the call method in JavaScript to do this:
var obj = {
count :0.say:function(){
console.log("Hello,world!")
this.count++; }}function fun(say){
say.call(obj);
}
var count = 0;
for(var i = 0; i <10; i++) fun(obj.say);console.log(obj.count);
console.log(count);
Copy the code
The call() method calls a function with a specified this value and one or more arguments given separately.
In fun, say.call(obj); Force say’s this to be bound to obj.
We can do this quickly with the bind function:
The bind() method creates a new function, and when bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments will be used as arguments to the new function.
The new binding
When we call a function using new, the following happens:
- Create an empty JavaScript object (that is {});
- Linking this object (setting its constructor) to another object;
- Use the new object created in Step 1 as the context for this;
- If the function does not return an object, this is returned.
So the following code is not surprising:
The binding order
Sometimes multiple binding rules apply to the same object, and the this binding follows these rules:
- The new call is bound to the newly created object. (New binding)
- Calls made by call, apply, or bind bind to the specified object. (Show binding)
- Called by a context object, bound to that context object. (Implicit binding)
4. No rules apply: bind to global object, undefined strictly (default binding).
You may find that implicit binding and default binding yield the same results in non-strict mode.
conclusion
My writing is so good that I use summary??
Don’t blow, point a praise bie~👍!