【Web 前端】彻底告别“this”指向困扰:从零开始掌握 JavaScript 中“this”的奥秘

简介: 【8月更文挑战第23天】在 JavaScript 中,`this` 关键字的指向是根据其调用上下文动态确定的,这对于 Web 前端开发者而言是一项核心技能。本文通过多个示例解释了 `this` 的指向规则:在对象方法中指向该对象,在独立函数中指向全局对象或 `undefined`,在事件处理器中指向触发事件的 DOM 元素,在构造函数中指向新创建的对象。此外,还介绍了一些技巧,如使用箭头函数、`bind` 方法以及在事件处理器中显式保存 `this` 的引用,以帮助开发者更好地理解和控制 `this` 的指向。

理解 this 的指向是每个 Web 前端开发者必须掌握的核心概念之一。在 JavaScript 中,this 关键字的指向根据调用上下文的不同而不同,这往往会让初学者感到困惑。本文将通过一系列实例来解析 this 的指向规则,并提供一些实用的技巧来帮助开发者更好地理解和使用 this

首先来看一个简单的例子,考虑一个对象,其中包含一个方法:

let obj = {
   
    name: 'Alice',
    greet: function() {
   
        console.log('Hello, my name is ' + this.name);
    }
};

obj.greet(); // 输出: Hello, my name is Alice

在这个例子中,当我们通过 obj.greet() 调用方法时,this 指向 obj 对象本身。这是因为在对象方法内部,this 默认指向该对象。然而,如果我们将这个方法赋值给一个变量,情况就会发生变化:

let obj = {
   
    name: 'Alice',
    greet: function() {
   
        console.log('Hello, my name is ' + this.name);
    }
};

let greet = obj.greet;
greet(); // 输出: Hello, my name is undefined

这里,由于 greet 函数不再是作为 obj 的属性被调用,因此 this 不再指向 obj。在非严格模式下,this 在这种情况下默认指向全局对象(在浏览器中通常是 window),但在严格模式('use strict';)下,则为 undefined。为了避免这种情况,可以使用箭头函数:

let obj = {
   
    name: 'Alice',
    greet: () => {
   
        console.log('Hello, my name is ' + this.name);
    }
};

let greet = obj.greet;
greet(); // 输出: Hello, my name is undefined

箭头函数没有自己的 this,而是继承自外围作用域。在这个例子中,this 指向全局对象,因为箭头函数是在全局作用域中被调用的。如果想要保持对象内的 this 值,可以使用 bind 方法:

let obj = {
   
    name: 'Alice',
    greet: function() {
   
        console.log('Hello, my name is ' + this.name);
    }
};

let greet = obj.greet.bind(obj);
greet(); // 输出: Hello, my name is Alice

bind 方法可以绑定函数的 this 值,使其始终指向 obj

接下来,我们来看看事件处理函数中的 this

<button id="btn">Click me</button>

<script>
document.getElementById('btn').addEventListener('click', function() {
    
    console.log(this.id); // 输出: btn
});
</script>

在这个 HTML 代码片段中,当按钮被点击时,事件处理器中的 this 指向触发事件的元素,即按钮本身。因此,this.id 正确地输出了按钮的 ID。

然而,如果我们尝试使用箭头函数,结果会有所不同:

<button id="btn">Click me</button>

<script>
document.getElementById('btn').addEventListener('click', () => {
    
    console.log(this.id); // 输出: undefined
});
</script>

这里,this 不再指向按钮元素,而是指向全局对象。这是因为箭头函数没有自己的 this,它继承自外部作用域。要解决这个问题,可以在事件处理器中显式地绑定 this

document.getElementById('btn').addEventListener('click', function() {
   
    const self = this;
    setTimeout(function() {
   
        console.log(self.id); // 输出: btn
    }, 100);
});

在这个例子中,我们在事件处理器内部保存了一个对 this 的引用,然后在 setTimeout 内部使用这个引用,确保 this 始终指向按钮元素。

最后,我们来看看构造函数中的 this

function Person(name) {
   
    this.name = name;
    this.greet = function() {
   
        console.log('Hello, my name is ' + this.name);
    };
}

let alice = new Person('Alice');
alice.greet(); // 输出: Hello, my name is Alice

在构造函数内部,this 指向新创建的对象。使用 new 关键字创建实例时,this 就会指向这个新对象。

总结来说,this 的指向取决于函数调用的方式。在对象方法中,this 指向对象本身;在独立函数中,默认指向全局对象或 undefined;在事件处理器中,this 指向触发事件的 DOM 元素;在构造函数中,this 指向新创建的对象。理解这些规则并熟练运用它们,将有助于避免许多常见的错误,并编写出更高质量的代码。

相关文章
|
5天前
|
前端开发
【前端web入门第四天】02 CSS三大特性+背景图
本文详细介绍了CSS的三大特性:继承性、层叠性和优先级,并深入讲解了背景图的相关属性,包括背景属性、背景图的平铺方式、位置设定、缩放、固定以及复合属性。其中,继承性指子元素自动继承父元素的文字控制属性;层叠性指相同属性后定义覆盖前定义,不同属性可叠加;优先级涉及选择器权重,包括行内样式、ID选择器等。背景图部分则通过具体示例展示了如何设置背景图像的位置、大小及固定方式等。
230 91
|
5天前
|
前端开发
【前端web入门第四天】01 复合选择器与伪类选择器
本文档详细介绍了CSS中的复合选择器与伪类选择器。复合选择器包括后代选择器、子代选择器、并集选择器和交集选择器,能够更精确地定位和样式化元素。后代选择器用于选中某元素的所有后代,子代选择器仅选中直接子元素。并集选择器可为多个标签设置相同样式,而交集选择器则选中同时满足多个条件的元素。此外,还介绍了伪类选择器,如鼠标悬停效果和超链接的不同状态。
44 32
【前端web入门第四天】01 复合选择器与伪类选择器
|
5天前
|
前端开发
【前端web入门第三天】02 CSS字体和文本
本文详细介绍了CSS中字体和文本的相关属性。字体部分涵盖字体大小、粗细、样式、行高、字体族及`font`复合属性,通过具体示例展示了如何设置和使用这些属性。文本部分则讲解了文本缩进、对齐方式、修饰线及文字颜色等属性,并提供了实用的代码示例。此外,还简要介绍了调试工具中的一些细节,如错误属性标识和属性生效状态的控制。
40 28
|
4天前
|
前端开发
【前端web入门第五天】03 清除默认样式与外边距问题【附综合案例产品卡片与新闻列表】
本文档详细介绍了CSS中清除默认样式的方法,包括清除内外边距、列表项目符号等;探讨了外边距的合并与塌陷问题及其解决策略;讲解了行内元素垂直边距的处理技巧;并介绍了圆角与盒子阴影效果的实现方法。最后通过产品卡片和新闻列表两个综合案例,展示了所学知识的实际应用。
22 11
|
4天前
|
前端开发
|
4天前
|
弹性计算 前端开发 容器
【前端web入门第六天】02 flex布局
Flex布局是一种现代CSS布局模式,通过给父元素设置`display: flex`,其子元素可自动挤压或拉伸。它包含弹性容器和弹性盒子,主轴默认为水平方向,侧轴为垂直方向。主轴对齐方式由`justify-content`属性控制,侧轴对齐方式包括`align-items`(针对所有子元素)和`align-self`(针对单个子元素)。修改主轴方向使用`flex-direction`属性,`flex`属性用于控制子元素在主轴上的伸缩比例。此外,`flex-wrap`属性允许子元素换行,而`align-content`属性则定义多行对齐方式。
|
4天前
|
前端开发
【前端web入门第五天】01 结构伪类选择器与伪元素选择器
本文介绍了CSS中的结构伪类选择器和伪元素选择器。结构伪类选择器如`nth-child`可根据元素结构关系进行选择,例如将列表中首个`&lt;li&gt;`元素背景设为绿色。伪元素选择器用于创建装饰性内容。
|
4天前
|
前端开发
【前端web入门第五天】02 盒子模型基础
本文档详细介绍了CSS中的盒子模型及其组成部分,包括内容区域、内边距、边框线和外边距。通过具体示例展示了如何设置边框线、内边距及外边距,并解释了尺寸计算方法和版心居中的技巧。内容丰富,示例清晰,有助于理解盒子模型在网页布局中的应用。
|
4天前
|
前端开发
【前端web入门第六天】01 CSS浮动
这是关于CSS布局第六天学习目标的介绍,主要解决多个`&lt;div&gt;`标签在同一行显示的问题,即一个在左边,另一个在右边。文中介绍了标准流、浮动及flex布局的概念,重点推荐使用flex布局。文章详细讲解了浮动的基本使用、布局技巧及清除浮动的方法,包括额外标签法、单伪元素法、双伪元素法和`overflow`隐藏法,并提供了示例代码帮助理解。
|
4天前
|
前端开发
前端web入门第四天】03 显示模式+综合案例热词与banner效果
本文档介绍了HTML中标签的三种显示模式:块级元素、行内元素与行内块元素,并详细解释了各自的特性和应用场景。块级元素独占一行,宽度默认为父级100%,可设置宽高;行内元素在同一行显示,尺寸由内容决定,设置宽高无效;行内块元素在同一行显示,尺寸由内容决定,可设置宽高。此外,还提供了两个综合案例,包括热词展示和banner效果实现,帮助读者更好地理解和应用这些显示模式。