This in JavaScript is always confusing and should be one of the well-known pitfalls of js. Personally, I also think that this in js is not a good design. Due to the late binding feature of this, it can be the global object, the current object, or... some people even do not use this because of the big pitfalls.
In fact, if you fully grasp the working principle of this, you will naturally not fall into these pits. Let’s take a look at what this will point to in the following situations:
1. this in the global code
1 alert(x);
// The value of global variable x is 2
this in the global scope will Will point to the global object, which is window in the browser.
2. Call as a simple function
function fooCoder(x) {
this.x = x;
}
fooCoder(2);
alert(x);
// The value of global variable x is 2
Here this points to the global object, which is window. In strict mode, it is undefined.
3. Call as method of object
var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth){
console.log(this.name + " says " + sth);
}
}
person.hello("hello world");
output foocoder says hello world. this points to the person object, which is the current object.
4. As a constructor
1 new FooCoder();
this inside the function points to the newly created object.
5. Internal function
var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth){
var sayhello = function(sth) {
console.log (this.name + " says " + sth);
};
sayhello(
}
person.hello("hello world");
//clever coder says hello world
In the inner function, This is not bound to the outer function object as expected, but to the global object. This is generally considered a design error in the JavaScript language, because no one wants this in the inner function to point to the global object. The way is to save this as a variable, generally agreed as that or self:
var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth){
var that = this ;
var sayhello = function(sth) {
console.log(that.name + " says " + sth);
};
sayhello(sth);
}
}
person.hello("hello world");
//foocoder says hello world
6. Use call and apply to set this
1 person.hello.call(person, "world");
apply is similar to call, except that the following parameters are passed through a The array is passed in instead of separately. The method definitions of the two are:
call(thisArg [, arg1, arg2,...]);
//Parameter list, arg1, arg2,...
apply(thisArg [, argArray] );
// Parameter array, argArray
Both are used to bind a function to a specific object. Naturally, this will be explicitly set to the first Parameters.
A brief summary
To simply summarize the above points, we can find that only the sixth point is confusing.
In fact, it can be summarized as the following points:
When a function is used as an object method. When called, this points to the object.
When the function is called as a fadeout function, this points to the global object (undefined in strict mode)
This in the constructor points to the newly created object
This in nested functions is not inherited The this of the upper-level function, if necessary, can be used to save the this of the upper-level function in a variable.
To summarize simply, if this is used in a function, this will point to the object only when the function is directly called by an object.
obj.foocoder();
foocoder.call(obj, ...);
foocoder.apply(obj, ...);
Go further
We may often write code like this:
1 $ ("#some-ele").click = obj.handler;
If this is used in handler, will this be bound to obj? Obviously not. After the assignment, the function is executed in the callback, and this will be bound to the $("#some-div") element. This requires understanding the execution environment of the function. This article does not intend to go into detail about the execution environment of the function. You can refer to the relevant introduction to the execution environment and scope chain in "Javascript Advanced Programming". What I want to point out here is that understanding the execution environment of the js function will help you better understand this.
So how can we solve the problem of callback function binding? A new method was introduced in ES5, bind():
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
When the binding function is called, the The parameter will be used as the this point of the original function when running. When the new operator is used to call the bound function, the parameter is invalid.
1 arg1, arg2, ...
When the bound function is called, these parameters are added The parameters of the bound function itself will be used as the parameters of the original function when running in order.
This method creates a new function, called a binding function. The binding function will use the first parameter passed into the bind method when creating it as this, and the second and subsequent parameters passed into the bind method plus the binding When the function is running, the parameters of the function itself are used as parameters of the original function in order to call the original function.
Obviously the bind method can solve the above problem well.
1
2 $("#some-ele").click(person.hello.bind(person));
//When the corresponding element is clicked, the output foocoder says hello world
In fact, this method is also very simple Easy to simulate, let’s take a look at the source code of the bind method in Prototype.js:
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift ();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
};