深入理解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
相关推荐
艾小逗3 小时前
vue3中的effectScope有什么作用,如何使用?如何自动清理
前端·javascript·vue.js
小小小小宇5 小时前
手写 zustand
前端
Hamm6 小时前
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
前端·vue.js·typescript
小小小小宇7 小时前
前端国际化看这一篇就够了
前端
大G哥7 小时前
PHP标签+注释+html混写+变量
android·开发语言·前端·html·php
whoarethenext7 小时前
html初识
前端·html
小小小小宇7 小时前
一个功能相对完善的前端 Emoji
前端
m0_627827527 小时前
vue中 vue.config.js反向代理
前端
Java&Develop7 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器
白泽talk7 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务