深入理解JavaScript 中的 this

1. this 是什么?

在 JavaScript 中,this 关键字用于指向调用它的对象。但它的指向并不是在编写代码时确定的,而是在 函数执行时 决定的。


2. this 在不同场景下的表现

2.1 作为对象的方法调用

javascript 复制代码
const obj = {
    name: 'Tom',
    sayHello() {
        console.log(this.name);
    }
};
obj.sayHello(); // Tom

解析this 指向 obj,因为 sayHello 是通过 obj 调用的。


2.2 直接调用函数(普通函数调用)

scss 复制代码
function show() {
    console.log(this);
}
show(); // 非严格模式下:window / 严格模式下:undefined

解析

  • 非严格模式 下,this 指向全局对象 window
  • 严格模式 下,thisundefined

2.3 构造函数调用

ini 复制代码
function Person(name) {
    this.name = name;
}
const p = new Person('Tom');
console.log(p.name); // Tom

解析this 指向新创建的实例 p


2.4 箭头函数中的 this

javascript 复制代码
const obj = {
    name: 'Tom',
    sayHello: () => {
        console.log(this.name);
    }
};
obj.sayHello(); // undefined

解析

  • 箭头函数不会创建自己的 this,它的 this 继承自定义它的作用域。
  • 这里 this 指向的是全局对象 window(在严格模式下 undefined)。

正确写法(使用普通函数):

javascript 复制代码
const obj = {
    name: 'Tom',
    sayHello() {
        console.log(this.name);
    }
};
obj.sayHello(); // Tom

2.5 this 丢失问题

javascript 复制代码
class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        console.log(this.name);
    }
}
const p = new Person('Tom');
const x = p.sayHello;
x(); // undefined

原因p.sayHello 只是一个函数的引用 ,它被赋值给变量 x,但 xp 没有任何关系了 。 在 JavaScript 中,this 只在函数被调用时确定,而不是在函数定义时

所以这里this 指向 window(非严格模式)或 undefined(严格模式),

解决方案

  • 使用 bind 绑定 this

    ini 复制代码
    const x = p.sayHello.bind(p);
    x(); // Tom
  • 使用箭头函数 (继承 this

    scss 复制代码
    const x = () => p.sayHello();
    x(); // Tom
  • 使用 call apply

    scss 复制代码
    x.call(p); // Tom
    x.apply(p); // Tom

3. this 在事件处理程序中

javascript 复制代码
document.querySelector("button").addEventListener("click", function() {
    console.log(this); // this 指向被点击的 button 元素
});

注意 :如果使用箭头函数,this 可能会指向 window 而不是按钮。

javascript 复制代码
document.querySelector("button").addEventListener("click", () => {
    console.log(this); // this 指向 window,而不是按钮
});

解决方案:用普通函数代替箭头函数。


4. thissetTimeoutsetInterval

javascript 复制代码
const obj = {
    name: 'Tom',
    sayHello() {
        setTimeout(function() {
            console.log(this.name);
        }, 1000);
    }
};
obj.sayHello(); // undefined

原因setTimeout 里的 this 指向 window(非严格模式)。

解决方案

  • 使用箭头函数 (继承 this

    javascript 复制代码
    sayHello() {
        setTimeout(() => {
            console.log(this.name);
        }, 1000);
    }

5. thiscallapplybind

call apply (手动绑定 this 并立即执行)

arduino 复制代码
function sayHello() {
    console.log(this.name);
}
const person = { name: 'Tom' };
sayHello.call(person); // Tom
sayHello.apply(person); // Tom

区别

  • call(thisArg, arg1, arg2, ...) 直接传参数。
  • apply(thisArg, [arg1, arg2, ...]) 以数组方式传参数。

bind (手动绑定 this ,但不会立即执行)

ini 复制代码
const boundFunc = sayHello.bind(person);
boundFunc(); // Tom

6. 总结

场景 this 指向
对象方法调用 调用它的对象
普通函数调用 window(非严格模式)或 undefined(严格模式)
构造函数调用 新创建的实例
箭头函数 继承外层作用域的 this
事件处理程序 绑定的 DOM 元素(普通函数)或 window(箭头函数)
setTimeout/setInterval window(非严格模式)或 undefined(严格模式)
call/apply/bind 绑定的对象

注意

  • 箭头函数不会创建自己的 this ,它会继承定义它的作用域的 this
  • 普通函数的 this 取决于调用方式,而不是定义位置
  • 手动绑定 this 可以用 bind call apply
相关推荐
驳是6 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea6 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持6 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者7 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn7 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
计算机魔术师9 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端
计算机魔术师9 小时前
OpenAI的AI代理偷偷给RubyGems下毒,我们却毫无察觉
前端
甲维斯9 小时前
0代码,0建模,3句话开发一个3D游戏!
前端·游戏·游戏开发
IT_陈寒10 小时前
Vue的响应式更新把我坑惨了,原来问题出在这
前端·人工智能·后端
tingke10 小时前
别再堆 AGENTS.md 了:前端团队的 Agent 上下文分层落地指南
前端