深入理解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 分钟前
H3初识——入门介绍之常用中间件
前端·javascript·react.js·中间件·前端框架·node.js·ecmascript
洛小豆36 分钟前
深入理解Pinia:Options API vs Composition API两种Store定义方式完全指南
前端·javascript·vue.js
洛小豆1 小时前
JavaScript 对象属性访问的那些坑:她问我为什么用 result.id 而不是 result['id']?我说我不知道...
前端·javascript·vue.js
叹一曲当时只道是寻常1 小时前
Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
前端·golang
超级土豆粉1 小时前
npm 包 scheduler 介绍
前端·npm·node.js
bug爱好者1 小时前
原生小程序如何实现跨页面传值
前端·javascript
随笔记1 小时前
uniapp开发的小程序输入框在ios自动填充密码,如何欺骗苹果手机不让自动填充
前端·ios·app
bug爱好者1 小时前
原生微信小程序最实用的工具函数合集
前端·javascript
3Katrina1 小时前
JS事件机制详解(2)--- 委托机制、事件应用
前端·javascript·面试
Allen Bright1 小时前
【CSS-15】深入理解CSS transition-duration:掌握过渡动画的时长控制
前端·css