what is this? 在 javascript 中,每个 function 都有一个 this 关键字的隐私绑定。当调用某个 function 时,这个 function 的 this 绑定将会被确定。
eg-1:1
2
3
4
5
6function test() {
console.log('this is ---', this);
}
test();
// this is ---Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
eg-2:1
2
3
4
5
6
7
8var test2 = {
console: function () {
console.log('this is ---', this);
}
};
test2.console();
// this is ---Object {console: function}
对于 eg-1 代码执行的结果可以看出,调用
test()
后, test函数 this 绑定的对象是 window 对象。因为在定义 test 函数的时候,这个函数会被加在 window 这个全局对象中,其实在执行test()
的时候,相当于window.test()
,这样可以明显的看出,调用test()
的对象是 window,也就是 this 绑定的对象是 window 。在 eg-2 中,当执行
test2.console()
时,调用 console 方法(函数)的对象为 test2,也就是 console 方法(函数)的 this 的值,就绑定了 test2 对象。
上面两个例子,描述的只是在函数体内的 this关键字。让我们来看一下,在全局中使用 this:
eg-3:1
2
3
4var name = 'aikin';
console.log(this.name);
// 'aikin'
- 从 eg-3这个例子看来,全局对象中的 this,表示的就是全局对象本身(window)。
通过 eg-1,eg-2,eg-3 可以知道,在不同的执行上下文中,this 的值是不相同的。即,在全局的执行上文中,this 表示的是全局对象本身(window);在函数执行上文中,this 的值绑定的是调用函数的对象。
接下来做个练习:1
2
3
4
5
6function practice() {
console.log('this in practice', this);
}
this.practice();
// 打印的结果会是?
在 javascript 中,随着函数的调用方式不同,将会导致函数的执行上下文不同,也就是将会导致函数内部 this 关键字绑定的对象不同。下面探索一下:构造函数调用,方法调用,函数调用。
a. 构造函数调用
构造函数和函数其实是一样,如果不使用关键字 new 调用,和其他的普通函数是一样的。
eg-4:1
2
3
4
5
6
7
8function User(name) {
this.name = name;
}
var me = new User ('aikin');
console.log(me.name);
//=> 'aikin'
- 使用 new 操作符来调用 User, 就会将User视为构造函数。 构造函数的调用会将一个全新的对象(也就是 new 出来的对象)作为 this 关键字的绑定对象。
b. 函数调用
函数调用,也就是直接调用函数,正如上面 eg-1 例子所描述的, 这时 this 绑定的对象是全局对象(window)。
c. 方法调用
当函数作为一个对象的属性时,这个函数就称为方法。
eg-5:1
2
3
4
5
6
7
8
9var obj = {
name : "aikin",
helllo : function () {
console.log('hello, ' + this.name)
}
};
obj.hello();
//=> "hello, aikin"
- 在这个例子(eg-5)中,obj 是 hello 方法的调用者,也就是说,hello 方法中的 this 关键字将会绑定 obj 对象。
所以,
函数调用时,将会将全局对象作为 this 的绑定对象。
方法调用时,方法调用者将会成为 this 的绑定对象。
构造函数,通过 new 关键字来调用后,将会产生一个新的对象作为其 this 的绑定对象。
参考
- 王群锋, 深入浅出 JavaScript 中的 this
- MDN, this
- David Herman, 《Effective JavaScript》