JavaScript中的this指向既可谓语言之精髓同时又是初学者的大坑,最近在学习过程中经历了许多磕磕碰碰,在此分享一下一些心得体会。
1. 最简单的情况:函数中的this
我们看下面一个例子
var name = 'Window';
var person = {
name: 'Person',
greeting: function () {
console.log('Hi! I\'m ' + this.name + '.');
}
};
var greeting = person.greeting;
greeting(); // Output #1: Hi! I'm Window.
person.greeting(); // Output #2: Hi! I'm Person.
从这个最简单的例子中可以看出,在最普通的情况下,this所指的对象就是调用它的对象:#1中是window
,#2中是person
。
2. this
的重定向
-
bind
绑定对象
有时候我们希望函数不论在何处调用都能表现得一致,即this
始终指向同一个对象,这时我们可以使用bind
来绑定该对象至函数,如下:
var name = 'Window';
var person = {
name: 'Person',
greeting: function () {
console.log('Hi! I\'m ' + this.name + '.');
}
};
var greetingByPerson = person.greeting.bind(person);
greetingByPerson(); // Output: Hi! I'm Person.
虽然是在最外层调用(即被window
调用),但函数已被绑定至person
,因此this
始终指向person
。
-
call
与apply
传入对象
有时候需要更灵活的使用函数,需要在不同场合使this
指向不同的对象,这时可以使用call
与apply
传入对象,如下:
var name = 'Window';
var person = {
name: 'Person',
greeting: function () {
console.log('Hi! I\'m ' + this.name + '.');
}
};
var stranger= {
name:'Stranger'
};
greeting=person.greeting;
greeting.call(person); // Output #1: Hi! I'm Person.
greeting.apply(person); // Output #2: Hi! I'm Person.
greeting.call(stranger); // Output #3: Hi! I'm Stranger.
greeting.apply(stranger); // Output #4: Hi! I'm Stranger.
由于stranger
对象中没有定义stranger.greeting
这一函数,我们可以使用greeting.call(stranger)
这样的方式来使this
指向stanger
;当然更多的时候这样的通用函数可能会定义在外层而非某一对象内。
apply
和call
的作用类似,其接受的第一个参数都是重定向的对象,区别在于接收后面参数的方法: call
接受连续的多个参数而apply
接受一个数组。
注意: 在node.js
中执行代码时最外层的调用对象会变成undefine
而非浏览器中的window