this 指向问题(call,apply,bind)剖析
2023-10-31 18:47:37
在 JavaScript 中,this
是一个特殊的,它代表当前执行代码的对象。在不同的上下文中,this
可以有不同的值,这被称为“this指向问题”。在 ES5 中,this
总是指向最后调用它的对象。
改变 this 指向
在 ES5 中,我们可以使用以下几种方法来改变 this
指向:
- 使用 ES6 箭头函数
- 在函数内部使用
_this = this;
- 使用
apply()
、call()
和bind()
- 使用
new
实例化一个对象
使用 ES6 箭头函数
ES6 箭头函数没有自己的 this
值,它总是继承其外层函数的 this
值。因此,我们可以使用箭头函数来改变 this
指向。例如:
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
const sayHello = () => {
console.log(`Hello, my name is ${this.name}`);
};
person.sayHello(); // Hello, my name is John
sayHello(); // 报错:this.name is undefined
在上面的例子中,person.sayHello()
方法中的 this
指向 person
对象,而 sayHello()
函数中的 this
指向 undefined
。这是因为 sayHello()
函数是一个箭头函数,它没有自己的 this
值,它继承了外层函数 (person.sayHello()
) 的 this
值。
在函数内部使用 _this = this;
我们可以在函数内部使用 _this = this;
来保存 this
的值,然后在函数内部使用 _this
来代替 this
。例如:
const person = {
name: 'John',
sayHello() {
const _this = this;
setTimeout(function() {
console.log(`Hello, my name is ${_this.name}`);
}, 1000);
}
};
person.sayHello(); // Hello, my name is John
在上面的例子中,我们使用 _this = this;
来保存 this
的值,然后在 setTimeout()
函数内部使用 _this
来代替 this
。这样,即使在 setTimeout()
函数内部,this
仍然指向 person
对象。
使用 apply()
, call()
和 bind()
apply()
, call()
和 bind()
是三个内置函数,它们可以改变 this
指向。
apply()
函数接受两个参数:第一个参数是this
的值,第二个参数是一个数组,包含要传递给函数的参数。call()
函数与apply()
函数类似,但它接受一个参数,而不是一个数组。bind()
函数返回一个新的函数,这个函数的this
值被固定为指定的值。
例如:
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
const sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
sayHello.apply(person); // Hello, my name is John
sayHello.call(person); // Hello, my name is John
const boundSayHello = sayHello.bind(person);
boundSayHello(); // Hello, my name is John
在上面的例子中,我们使用 apply()
、call()
和 bind()
函数来改变 this
指向。
使用 new
实例化一个对象
当我们使用 new
关键字实例化一个对象时,this
指向这个新对象。例如:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person('John');
person.sayHello(); // Hello, my name is John
在上面的例子中,我们使用 new
关键字实例化了一个 Person
对象,然后调用 sayHello()
方法。this
指向 person
对象,因此 this.name
等于 'John'
。
总结
在本文中,我们详细分析了this指向问题,并介绍了ES6箭头函数、apply、call、bind和new实例化对象等改变this指向的方法。希望通过本文,你能对this指向问题有更深入的理解。