深入理解 JavaScript 中的 this 指向

前言

正值春招火热招聘阶段,我近期在复习JavaScript的相关知识点,其中"this"知识点是前端面试中高频面试内容,因此整理和总结一篇相关知识点文章和大家分享!
在 JavaScript 中,this 是一个非常重要的关键字,它在函数和对象操作中扮演着关键角色。然而,this 的指向规则并不总是直观的,这让很多初学者感到困惑。本文将通过通俗易懂的方式,结合实际代码示例,帮助你彻底理解 this 的指向规则。

一、this的指向规则

this 的指向取决于函数的调用方式,而不是函数的定义方式。虽然"谁调用它,this 就指向谁 "这种说法有一定道理,但并不完全准确。以下是 this 指向的几种常见情况:

1. 全局环境中的this

在全局环境下调用函数时,this 的指向会根据是否开启严格模式而有所不同。

  • 非严格模式 :this 指向全局对象(浏览器中是 window,Node.js 中是 global)。

  • 严格模式 :this 指向 undefined。

javascript 复制代码
function f1() {
    console.log(this);
}
​
function f2() {
    'use strict';
    console.log(this);
}
​
f1(); // 非严格模式:window 或 global
f2(); // 严格模式:undefined

2. 使用 new 调用构造函数

当使用 new 关键字调用函数时,this 会被绑定到新创建的对象上。

javascript 复制代码
function Person(name) {
    this.name = name;
}
​
const person = new Person('Alice');
console.log(person.name); // 输出:Alice
console.log(person); // 输出:{ name: 'Alice' }

在这个例子中,this 指向了通过 new 创建的 person 对象。

3. 使用 call、apply、bind 显式绑定 this

call、apply 和 bind 是 JavaScript 中用来显式改变函数内部 this 指向的方法。

  • call 和 apply :立即执行函数,并将 this 绑定到指定对象。call 和 apply 的区别在于参数的传递方式:call 接收多个参数,apply 接收一个数组作为参数。
javascript 复制代码
const obj = { name: 'Bob' };
​
function greet() {
    console.log(`Hello, ${this.name}!`);
}
​
greet.call(obj); // 输出:Hello, Bob!
greet.apply(obj); // 输出:Hello, Bob!
  • bind:返回一个新函数,该函数的 this 指向被永久绑定到指定对象。
javascript 复制代码
const greetBob = greet.bind(obj);
greetBob(); // 输出:Hello, Bob!

4. 通过上下文对象调用函数

当通过对象的方法调用函数时,this 指向该对象。

javascript 复制代码
const student = {
    name: 'Alice',
    greet: function() {
        console.log(`Hello, ${this.name}!`);
    }
};
​
student.greet(); // 输出:Hello, Alice!

如果函数被赋值给其他变量后调用,this 的指向会丢失,恢复到全局对象。

javascript 复制代码
const greet = student.greet;
greet(); // 输出:Hello, undefined!

5. 箭头函数中的this

箭头函数是 ES6 引入的一种简化语法,它的 this 指向在定义时就已经确定,始终指向外层作用域的 this。

javascript 复制代码
const obj = {
    name: 'Alice',
    greet: () => {
        console.log(`Hello, ${this.name}!`);
    }
};
​
obj.greet(); // 输出:Hello, undefined!

在这个例子中,箭头函数的 this 指向全局对象,而不是obj。

二、更复杂的场景

1、事件处理中的 this

在 DOM 事件处理中,事件处理函数的 this 指向绑定事件的元素。

javascript 复制代码
document.getElementById('button').addEventListener('click', function() {
    console.log(this); // 指向绑定事件的按钮元素
});

如果事件处理函数是一个箭头函数, this 的指向会继承自外层作用域。

javascript 复制代码
const button = document.getElementById('button');
button.addEventListener('click', () => {
    console.log(this); // 指向全局对象(浏览器中是 window)
});

2、嵌套函数中的 this

在嵌套函数中,this 的指向可能会变得复杂。普通函数的 this 指向取决于调用方式,而箭头函数的this 指向则继承自外层作用域。

javascript 复制代码
const obj = {
    name: 'Alice',
    greet: function() {
        const inner = () => {
            console.log(`Hello, ${this.name}!`);
        };
        inner();
    }
};
​
obj.greet(); // 输出:Hello, Alice!

在这个例子中,箭头函数 inner 的 this 继承自外层的 greet 函数的 this,指向 obj。

三、总结

this 的指向规则虽然复杂,但只要掌握以下要点,就可以轻松应对:

  1. 全局环境 :非严格模式下指向全局对象,严格模式下指向 undefined。

  2. 构造函数 :使用 new 时,this 指向新创建的对象。

  3. 显式绑定 :通过 call、apply、bind 可以显式改变 this 的指向。

  4. 上下文对象 :通过对象调用函数时,this 指向该对象。

  5. 箭头函数 :this 指向外层作用域。

相关推荐
老男孩游戏时光8 分钟前
Electron 桌面应用开发入门,前端也能写客户端
前端
默_笙13 分钟前
🚊 别再让 AI 的记忆写两遍了:PostgreSQL 把关系查询和语义检索装进一张表
前端·javascript
进击的明明14 分钟前
TypeScript速通笔记(下)
前端·面试·typescript
lzhdim17 分钟前
C#不为人知的10个魔法特性:资深开发者也会震惊的底层奥秘
java·前端·javascript·算法·c#
weixin_3077791324 分钟前
C++代码实现MATLAB中的pade函数功能
开发语言·c++·算法·matlab
ProcessOn官方账号31 分钟前
java IO操作 你快速认识IO的相关基本知识
java·开发语言
神仙别闹1 小时前
基于C++实现的(控制台)学校开课查询系统
开发语言·c++
zach1 小时前
前端落地实战:Next.js 项目 Nginx + PM2 生产部署全流程(附踩坑总结)
前端·pm2·next.js
overmind1 小时前
oeasy教h5前端001 修改的乐趣_直接修改在线网页
前端
只睡四小时2 小时前
JS 手写 D-pad 空间导航:电视端焦点引擎实战
android·开发语言·前端·javascript·ecmascript·hls·空间导航