改变this的指向主要有三个方法,分别是call(),apply(),bind()。先看下面的例子
var name = '张三', age = 18;
var obj = {
name: '李四',
fn: function() {
console.log("My name is " + this.name + ", i am " + this.age + ' years old !');
}
}
var fn = obj.fn;
fn(); // My name is 张三, i am 18 years old !
此时,方法中的this指向的是window,因为函数中的this取决于调用它的实例对象。我们可以换一种写法,如下:
var name = '张三', age = 18;
var obj = {
name: '李四',
fn: function() {
console.log("My name is " + this.name + ", i am " + this.age + ' years old !');
}
}
var fn = obj.fn;
fn(); //My name is 张三, i am 18 years old !
obj.fn(); //My name is 李四, i am undefined years old !
此时,方法中的this指向的是obj对象。但是有时候我们想把函数存储在一个变量中,就像上面的fn一样,我们想延后执行,但是又想this指向obj怎么办,这是就可以使用call(),apply(),bind()了, 如下:
var name = '张三', age = 18;
var obj = {
name: '李四',
fn: function() {
console.log("My name is " + this.name + ", i am " + this.age + ' years old !');
}
}
var fn = obj.fn;
fn(); //My name is 张三, i am 18 years old !
obj.fn(); //My name is 李四, i am undefined years old !
fn.call(obj); //My name is 李四, i am undefined years old !
fn.apply(obj); //My name is 李四, i am undefined years old !
fn.bind(obj); // 没打印
fn.bind(obj)(); //My name is 李四, i am undefined years old !
需要注意的是,fn.bind(obj)返回的是一个函数,我们需要额外的执行。另外,这三个方法在使用上还有一点小区别,比如我们的方法,就是传参的区别。如下
var name = '张三', age = 18;
var obj = {
name: '李四',
fn: function(a,aa) {
console.log("My name is " + this.name + ", i am " + this.age + ' years old !');
console.log(a, + " " + aa);
}
}
var b = obj.fn;
b.call(obj, 1, 2); //参数写在后面
b.apply(obj, [1, 2]); //参数写在第二参数,以数组的形式
b.bind(obj, 1)(2); //写在两个括号都行,等价于 b.bind(obj2, 1, 2)() 或者 b.bind(obj2)(1, 2)
三个改变this指向的大致用法就是这样了,后续研究下它们的具体实现方式。