你真的懂this吗?一、什么是 this? 在 JavaScript 中,this 是一个引用当前执行上下文的对象。执行
this关键字是 JavaScript 中最重要和最容易混淆的概念之一。它的值不仅取决于代码的执行上下文,还可以通过不同的调用方式动态改变。本文将详细探讨 JavaScript 中this的工作原理、不同情况下this的取值,以及如何正确使用this关键字。
一、什么是 this?
在 JavaScript 中,this 是一个引用当前执行上下文的对象。执行上下文指的是代码运行时的环境,this 的值会根据执行上下文的不同而变化。this 关键字允许函数在不同的上下文中访问和操作对象。
二、this 的工作原理
JavaScript 中 this 的值取决于函数的调用方式。以下是常见的调用方式及其对应的 this 绑定规则:
- 全局上下文中的 this
- 对象方法中的 this
- 构造函数中的 this
- 箭头函数中的 this
- 显式绑定的 this
1. 全局上下文中的 this
在全局执行上下文中(即在函数之外),this 引用的是全局对象。在浏览器中,全局对象是 window,在 Node.js 中则是 global。
示例:
console.log(this); // 浏览器中输出 window 对象,Node.js 中输出 global 对象
在非严格模式下,未绑定到任何对象的函数中的 this 默认指向全局对象。
示例:
function showThis() {
console.log(this);
}
showThis(); // 浏览器中输出 window 对象,Node.js 中输出 global 对象
在严格模式 (use strict) 下,this 不再指向全局对象,而是 undefined。
示例:
"use strict";
function showThis() {
console.log(this);
}
showThis(); // 输出 undefined
2. 对象方法中的 this
当 this 在对象的方法中使用时,它指向调用该方法的对象。
示例:
const obj = {
name: "Alice",
showThis: function () {
console.log(this);
},
};
obj.showThis(); // 输出 obj 对象
在这个例子中,showThis 方法中的 this引用 obj 对象,这是因为 showThis 是由 obj 调用的。
如果将方法赋值给一个变量,再调用该变量,this 的指向会改变。
示例:
const obj = {
name: "Alice",
showThis: function () {
console.log(this);
},
};
const anotherFunc = obj.showThis;
anotherFunc(); // 浏览器中输出 window 对象,Node.js 中输出 global 对象
由于 anotherFunc 是在全局上下文中调用的,this 指向了全局对象。
3. 构造函数中的 this
当使用 new 关键字调用函数时,this 指向新创建的对象。
示例:
function Person(name) {
this.name = name;
}
const person = new Person("Alice");
console.log(person.name); // 输出 "Alice"
在这个例子中,this 在构造函数 Person 中引用新创建的对象,因此 this.name = name 将 name 属性绑定到新对象上。
箭头函数中的 this
箭头函数与传统函数的一个重要区别在于它们不绑定自己的 this 值。箭头函数中的 this 始终指向它被定义时所在的词法作用域中的 this 值。
示例:
const obj = {
name: "Alice",
showThis: function () {
const arrowFunc = () => {
console.log(this);
};
arrowFunc();
},
};
obj.showThis(); // 输出 obj 对象
在这个例子中,箭头函数 arrowFunc 的 this 继承自 showThis 方法的 this,因此它指向 obj。
即使箭头函数被赋值给另一个变量,其 this 绑定也不会改变。
示例:
const obj = {
name: "Alice",
showThis: function () {
const arrowFunc = () => {
console.log(this);
};
return arrowFunc;
},
};
const anotherFunc = obj.showThis();
anotherFunc(); // 输出 obj 对象
5. 显式绑定的 this
JavaScript 提供了三种方法来显式绑定 this 值:call、apply 和 bind。
call和apply: 这两个方法用于立即调用函数,并在调用时显式设置this的值。它们的区别在于传递参数的方式,call接受多个参数,而apply接受一个参数数组。
示例:
function showName() {
console.log(this.name);
}
const person1 = { name: "Alice" };
const person2 = { name: "Bob" };
showName.call(person1); // 输出 "Alice"
showName.apply(person2); // 输出 "Bob"
-
bind:bind方法用于创建一个新函数,并永久绑定this的值。新函数可以稍后调用。示例:
function showName() {
console.log(this.name);
}
const person = { name: "Alice" };
const boundFunc = showName.bind(person);
boundFunc(); // 输出 "Alice"
在这个例子中,bind 返回一个新函数,该函数的 this 永远绑定到 person 对象。
三、this 关键字的实际应用
理解和正确使用 this 是编写复杂 JavaScript 应用程序的关键。以下是一些实际应用场景:
1. 在对象方法中访问对象属性
this 使得方法能够访问和操作调用它的对象的属性。
示例:
const counter = {
value: 0,
increment: function () {
this.value++;
console.log(this.value);
},
};
counter.increment(); // 输出 1
counter.increment(); // 输出 2
2. 在事件处理程序中引用元素
在 DOM 事件处理程序中,this 通常引用触发事件的元素。
示例:
document.getElementById("myButton").addEventListener("click", function () {
console.log(this.id); // 输出 "myButton"
});
在这个例子中,this 引用触发点击事件的按钮元素。
3. 使用 bind 创建回调函数
bind 方法常用于将 this 绑定到特定对象,特别是在回调函数中。
示例:
function Timer() {
this.seconds = 0;
setInterval(
function () {
this.seconds++;
console.log(this.seconds);
}.bind(this),
1000
);
}
const timer = new Timer();
// 每秒输出 1, 2, 3, ...
在这个例子中,bind 方法确保 setInterval 的回调函数中的 this 指向 Timer 实例。
四、总结
this 关键字在 JavaScript 中是一个强大且灵活的工具,但同时也是一个容易混淆的概念。它的值取决于函数的调用方式,而不是函数定义的位置。在编写 JavaScript 代码时,理解 this 的工作原理和不同的绑定规则非常重要,这样可以避免常见的错误,如 this 指向意外的对象。
P.S.
本文首发于我的个人网站www.aifeir.com,若你觉得有所帮助,可以点个爱心鼓励一下,如果大家喜欢这篇文章,希望多多转发分享,感谢大家的阅读。
转载自:https://juejin.cn/post/7406899773796483083