JavaScript 中 this 指向问题
|
zhenglin
2025年12月1日 16:0
本文热度 524
|
一、Bug 场景
在一个 JavaScript 的网页交互项目中,有一个构造函数定义了一个对象,该对象包含一个方法用于更新 DOM 元素的文本内容。同时,为了实现异步操作,在这个方法内部使用了 setTimeout 来模拟一些延迟任务。
二、代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
<meta name="viewport" content="width=device - width, initial - scale = 1.0">
<title>this指向问题</title>
</head>
<body>
<div id="target"></div>
<script>
function DOMUpdater() {
this.targetElement = document.getElementById('target');
this.updateText = function () {
setTimeout(function () {
this.targetElement.textContent = '更新后的文本';
}, 1000);
};
}
const updater = new DOMUpdater();
updater.updateText();
</script>
</body>
</html>
三、问题描述
1.预期行为:等待 1 秒后,id 为 target 的 div 元素的文本内容应更新为 “更新后的文本”。
2.实际行为:在控制台中会报错 Uncaught TypeError: Cannot set property 'textContent' of null。这是因为在 setTimeout 内部的回调函数中,this 的指向发生了变化。在非严格模式下,setTimeout 回调函数中的 this 指向全局对象(在浏览器环境中是 window),而不是 DOMUpdater 实例对象。由于 window 中没有 targetElement 属性,所以会导致 this.targetElement 为 null,进而引发错误。
四、解决方案
使用箭头函数:箭头函数没有自己的 this,它的 this 继承自外层作用域,这样就可以保持 this 指向 DOMUpdater 实例对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
<meta name="viewport" content="width=device - width, initial - scale = 1.0">
<title>this指向问题 - 箭头函数解决</title>
</head>
<body>
<div id="target"></div>
<script>
function DOMUpdater() {
this.targetElement = document.getElementById('target');
this.updateText = function () {
setTimeout(() => {
this.targetElement.textContent = '更新后的文本';
}, 1000);
};
}
const updater = new DOMUpdater();
updater.updateText();
</script>
</body>
</html>
使用变量保存 this:在 updateText 方法内部,使用一个变量(通常命名为 self 或 that)来保存 this 的值,然后在 setTimeout 回调函数中使用这个变量。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
<meta name="viewport" content="width=device - width, initial - scale = 1.0">
<title>this指向问题 - 变量保存this解决</title>
</head>
<body>
<div id="target"></div>
<script>
function DOMUpdater() {
this.targetElement = document.getElementById('target');
this.updateText = function () {
const self = this;
setTimeout(function () {
self.targetElement.textContent = '更新后的文本';
}, 1000);
};
}
const updater = new DOMUpdater();
updater.updateText();
</script>
</body>
</html>
使用 bind 方法:bind 方法可以创建一个新的函数,在这个新函数中,this 被绑定到指定的对象。
代码高亮:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
<meta name="viewport" content="width=device - width, initial - scale = 1.0">
<title>this指向问题 - bind解决</title>
</head>
<body>
<div id="target"></div>
<script>
function DOMUpdater() {
this.targetElement = document.getElementById('target');
this.updateText = function () {
setTimeout(function () {
this.targetElement.textContent = '更新后的文本';
}.bind(this), 1000);
};
}
const updater = new DOMUpdater();
updater.updateText();
</script>
</body>
</html>
参考文章:原文链接
该文章在 2025/12/1 16:00:30 编辑过