深入理解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
相关推荐
李鸿耀9 分钟前
仅用几行 CSS,实现优雅的渐变边框效果
前端
码事漫谈28 分钟前
解决 Anki 启动器下载错误的完整指南
前端
im_AMBER1 小时前
Web 开发 27
前端·javascript·笔记·后端·学习·web
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo2 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
DoraBigHead3 小时前
React 架构重生记:从递归地狱到时间切片
前端·javascript·react.js
彩旗工作室4 小时前
WordPress 本地开发环境完全指南:从零开始理解 Local by Flywhee
前端·wordpress·网站