深入理解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
相关推荐
程序员Sunday几秒前
还在用 setTimeout?试试 requestIdleCallback 吧!
前端·javascript
非凡ghost2 分钟前
Flameshot(开源免费的截图工具) 中文绿色版
前端·javascript·后端
神秘的猪头4 分钟前
Stylus项目实战:cards
前端·javascript
MiyueFE5 分钟前
使用Powertools for Amazon Lambda简化Amazon AppSync Events集成
前端·aws
神秘的猪头5 分钟前
弹性布局vsinline-block
前端
王六岁5 分钟前
# 🐍 前端开发 0 基础学Python小结 Python数据类型使用场景与用途指南
前端·python
平生不晚8 分钟前
优化使用img标签加载svg大图导致的内存开销
前端·浏览器
Zyx20078 分钟前
弹性布局:告别“挤来挤去”的CSS布局时代——深入理解 Flexbox
前端·css
Apifox10 分钟前
Apifox 10 月更新|支持实时预览在线文档个性化配置的效果、性能优化、测试能力升级
前端·后端·测试
玉宇夕落11 分钟前
🔥 一行代码让网页“活”起来!前端黑科技 Stylus + Flex 实战,小白也能写出酷炫交互动画!
前端·javascript