JavaScript 中的 this 关键字是一个非常重要但有时会令人困惑的概念。它的值取决于函数的调用方式,而不是定义方式。在 ES5 中,我们经常需要控制 this 的指向,尤其是在异步编程和回调函数中。
1. this 的基本行为
在 JavaScript 中,this 的值通常取决于函数的调用方式:
- 在全局范围内,
this指向全局对象(在浏览器中是window)。 - 当函数作为某个对象的方法调用时,
this指向那个调用者对象。 - 当函数作为构造函数使用,通过
new关键字调用时,this指向新创建的对象。
var num = 100
var obj = {
num: 200,
inner: {
num: 300,
print: function () {
console.log(this.num)
}
}
}
obj.inner.print()
很明显,这段代码的输出结果是300,this指向了它的调用者inner
2. 使用 call 和 apply 修改 this 的作用域
call 和 apply 都用于调用函数,并允许你为函数的执行指定 this 的值。它们的不同之处在于如何传递参数:
call方法接受一个参数列表。apply方法接受一个包含多个参数的数组。
function showDetails(age, job) {
console.log(this.name + " is " + age + " years old and is a " + job + ".");
}
var person = {
name: "John"
};
showDetails.call(person, 30, "developer"); // John is 30 years old and is a developer.
showDetails.apply(person, [30, "developer"]); // John is 30 years old and is a developer.
3. 使用 bind 创建新函数
bind 方法创建一个新的函数,在这个新函数中 this 被指定为 bind 的第一个参数,其余参数将作为新函数的预设参数。
function greet(greeting) {
console.log(greeting + ", " + this.name);
}
var person = {
name: "John"
};
var greetPerson = greet.bind(person);
greetPerson("Hello"); // Hello, John
4. ES6 箭头函数与 this
ES6 引入了箭头函数,它们不仅语法更简洁,而且 this 的行为也与普通函数不同。箭头函数不绑定自己的 this,它们继承上一层作用域链中的 this 值。
var person = {
name: "John",
activities: ["coding", "reading", "gaming"],
showActivities: function() {
this.activities.forEach((activity) => {
console.log(this.name + " likes " + activity);
});
}
};
person.showActivities(); // John likes coding
// John likes reading
// John likes gaming
小结
通过使用 call、apply 和 bind,我们可以在 JavaScript ES5 中灵活地控制函数的 this 指向。而 ES6 的箭头函数为我们处理 this 提供了更简洁有效的方式,特别是在嵌套函数和回调函数中。