你真的懂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