在JavaScript中,this 总是让人困惑,它是JavaScript中最常见的陷阱之一。 this 在JavaScript中不是一个好的设计(你可以参考JavaScript的一些其他设计缺陷这里),由于它的惰性绑定特性,它可以是一个全局对象,当前对象,或者... 有些人甚至避免在JavaScript中使用 this。
实际上,如果你掌握了 this 的工作原理,你就会知道如何避开这些陷阱。 让我们看看在以下情况下 this 指向什么。
1. 在全局作用域代码中
alert(this)//window
在全局作用域代码中,this 将指向全局对象(通常在Web浏览器中是 window)。
2. 在纯函数调用中
function fooCoder(x) {
this.x = x;
}
fooCoder(2);
alert(x);// 全局变量 x 的值为 2
这里 this 也指向全局对象,因为在全局作用域中定义的函数实际上是全局对象的一个方法。 所以 this 将是全局对象。 在严格模式下,this 将是 undefined。
3. 在对象的方法调用中
var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth){
console.log(this.name + " says " + sth);
}
}
person.hello("hello world");
输出将是 "foocoder says hello world"。 this 将指向 person 对象,即调用该方法的当前对象。
4. 在构造函数中
new FooCoder();
在构造函数中,this 将指向使用 new 关键字新创建的对象。
5. 在私有函数调用中
var name = "clever coder";
var person = {
name : "foocoder",
hello : function(sth){
var sayhello = function(sth) {
console.log(this.name + " says " + sth);
};
sayhello(sth);
}
}
person.hello("hello world");//clever coder says hello world
在私有函数中,this 不会绑定到外部方法的对象,而是绑定到全局对象。 这被认为是JavaScript的设计缺陷,因为没有人希望私有函数中的 this 在这里指向全局对象。 一般的解决方案是将 this 赋值给另一个变量,并在私有函数中引用该变量。
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. 在 call() 或 apply() 中
person.hello.call(person, "world");
apply() 和 call() 类似,唯一的区别是第一个参数之后传入的参数。 在 apply() 中,其他参数将通过一个数组传递,而在 call() 中,其他参数将分别传递。
call( thisArg [,arg1,arg2,… ] ); // 参数列表,arg1,arg2,... apply(thisArg [,argArray] ); // 参数列表,argArray
传入的第一个参数是 this 将指向的对象。 我们可以指定任何对象让 this 指向它。
7. 其他
我们可能会经常看到以下代码:
$("#some-ele").click = obj.handler;
如果我们在 handler 中使用 this,this 会绑定到 obj 吗? 显然不会,在赋值之后,该函数在回调函数中被调用,this 将绑定到 $("#some-div") 元素。 这是我们需要理解的——执行上下文。
那么我们如何在回调函数中指定 this 对象为我们想要的对象呢? 在ECMAScript 5中,有一个 bind() 方法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 将是我们想要成为的 this 对象。
$("#some-ele").click(person.hello.bind(person));
现在 this 将是 person 对象
在Prototype.js中,我们可以找到 bind() 的实现:
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)));
};
};
结论
1. 当函数作为对象的方法被调用时,this 将指向该对象
2. 当在纯函数调用中时,this 将是全局对象(在严格模式下,this 将是 undefined)
3. 在构造函数中,this 将是新创建的对象
一句话概括,this 总是指向调用该函数的对象。
No comment for this article.