this指向问题一直是个比较头疼的问题,有些概念虽说也懂,但每次用的时候又会出错,最近编写一些代码时常用到this,所以又结合书上的概念系统的总结了一下:
this指向与执行环境有关,在全局执行环境中,this指向window,所以在全局中输入
console.log(this);
会得到:
而在函数执行环境中,this指向取决于函数属于哪种调用模式。
在《JavaScript语言精粹》第四章有讲到函数四种调用模式:方法调用模式,函数调用模式,构造器调用模式和apply调用模式。
1、 方法调用模式
当一个函数作为一个对象的方法时,其内部this指向当前调用的对象,如:
var obj = {
value: 0,
getValue: function () {
console.log(this);
return this.value;
}
}
obj.getValue();
结果如下:
2、 函数调用模式
当函数直接通过函数名调用时,无论是全局对象上的函数还是内部函数,this都是指向全局对象,如:
function foo() {
console.log(this);
var bar = function () {
console.log(this);
}
return bar;
}
(foo())();
结果:
值得一提的是我们常常会直接传递一个匿名函数,如调用setTimeout函数,或者向jQuery对象传递一个函数使其直接执行,这时由于在函数内部是通过函数调用模式调用的,所以匿名函数内部的this指向全局对象。
3、 构造器调用模式
“如果一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype成员对象,同时this会被绑定到那个新对象上”,如:
function Foo() {
this.value = 0;
console.log(this);
}
var myFoo = new Foo();
结果:
而如果不通过new调用,则this指向全局对象。
而对于原型对象而言,this指向取决于谁在调用,如果是对象本身则指向原型对象,如果是对象实例,则指向对象实例。如:
function Foo() {
this.value = 0;
}
Foo.prototype.getValue = function () {
console.log(this);
return this.value;
}
var myFoo = new Foo();
Foo.prototype.getValue();
myFoo.getValue();
结果:
4、 apply调用模式
apply可以让函数在某个指定的对象里被调用,就好像该函数是被指定的对象调用一样,所以函数内部的this指向指定的对象。如:
var obj = {
value: 0
}
var foo = function () {
console.log(this);
return this.value;
}
foo.apply(obj);
foo();
结果:
apply可以使回调函数的this依然指向该对象,通过这个特性可以在编写jQuery插件时在回调函数内部依然使用当前对象。如:
var obj = {
value: 0,
getValue: function (callback) {
callback();
callback.apply(this);
return this.value;
}
}
obj.getValue(function () {
console.log(this)
});
结果:
所以this指向关键在于观察其所处的执行环境以及函数是属于哪种调用模式,平时多用,总结错误就能熟练运用。