首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >为什么赋值过程会丢失this

为什么赋值过程会丢失this

作者头像
watermelo37
发布2025-11-25 08:37:57
发布2025-11-25 08:37:57
510
举报
文章被收录于专栏:前端专精前端专精

作者:watermelo37 CSDN全栈领域优质创作者、华为云云享专家、阿里云专家博主、腾讯云“创作之星”特邀作者、火山KOL、支付宝合作作者,全平台博客昵称watermelo37。 一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。 --------------------------------------------------------------------- 温柔地对待温柔的人,包容的三观就是最大的温柔。 ---------------------------------------------------------------------

为什么赋值过程会丢失this

一、场景重现

小瓜很久以前写过一篇《【最简单最全面】一文讲清楚五大this指向,this到底指向哪里?》,能够通过原理 -> 案例 -> 对比的帮助大家快速学习和辨别各种场景下的 this 指向,有兴趣的读者请移步:【最简单最全面】一文讲清楚五大this指向,this到底指向哪里?

文中详细解释了各种场景下的 this 指向,但只是简单提了提 this 丢失的情况,最近我在开发中就遇到了一个 this 丢失的场景,代码简化如下:

代码语言:javascript
复制
window.identity = 'The Window'

let object = {
    identity: 'My Object',
    getIdentity () {
        return this.identity;
    }
};

// 简单思考一下,1和2的返回分别是什么?

(object.getIdentity());                      // 1
(object.getIdentity = object.getIdentity)(); // 2

猜出答案不难,首先1肯定是My Object,如果对这个有疑问建议先点击上述链接前往了解,那2是什么呢?既然提到了 this 丢失,那2的this肯定会变,那就只能是The Window 了,可是为什么呢?

二、复现问题:同一个函数,不同调用方式

1、问题解答

首先 (object.getIdentity()) 这是一个典型的作为对象方法调用,所以 this → object 。获取到的值即为“My Object”。

但第二个:(object.getIdentity = object.getIdentity)() 在赋值运算符执行后,返回的是右侧的值,也就是那个函数本身。换句话说,这行代码等价于:

代码语言:javascript
复制
let temp = object.getIdentity; // 赋值表达式
(temp)();                      // 调用表达式

temp() 是普通函数调用,其 this 默认指向全局对象(浏览器下为 window)。于是就得到了结果 2:“The Window”。

2、Js中this绑定取决于调用方式

在Js中,除了箭头函数(箭头函数的this在定义的时候就确定下来了,并且无法修改)外的函数 this 绑定,都是取决于调用的方式而不是定义的方式。大致规则如下:

  • obj.fn() → this = obj
  • fn() → this = window 或 undefined(严格模式)
  • new fn() → this = 新对象
  • fn.call(obj) → this = obj
  • obj.fn.bind(obj) → this 永久绑定 obj
代码语言:javascript
复制
// 因此会把 obj 设为 this
(obj.method)()

// 但是这个就就不再有 obj 参与,结果 this → window。
(let tmp = obj.method; tmp)()
3、为什么赋值表达式会导致 this 的丢失?

核心原因在于:赋值表达式的返回值是“右侧的值本身”,不保留任何引用信息。

代码语言:javascript
复制
object.getIdentity = object.getIdentity

// 上面语句的结果只是一个函数对象,而不携带其他的信息

function getIdentity() { ... }

而方法调用为什么能绑定 this?因为属性访问表达式会产生一个带有 base 对象的 “Reference 类型”。这样就可以追溯方法调用方的其他属性,最后获取具体的 this 指向。

三、ECMAScript 规范层面的解释

语言规范中有一个关键术语:Reference 类型(只存在于规范,不可直接访问)

当你写出:object.getIdentity 它并不是简单取值,而是生成一个 Reference { base: object, name: 'getIdentity' } 当你使用括号调用:(object.getIdentity)() 规范执行的是:Call(F, thisArgument = Reference.base)

这样就会保留 this = object 的引用信息,但赋值表达式会破坏 Reference 信息。

(object.getIdentity = object.getIdentity) 左边的 object.getIdentity 是一个 Reference,右边是函数值,赋值表达式把右侧值写入左侧,返回值为函数本身,不带 Reference Base。

于是就变成了普通函数调用 → this 指向 window。

四、问题总结

赋值过程丢失this 的核心原因主要是以下两点:

①赋值表达式的返回值是“右侧值本身” → 丢失了 base 信息

(object.getIdentity = object.getIdentity) ↓ 返回的是函数本身,而非“带 base 的引用”

②() 运算符的 this 绑定取决于“调用表达式的结构”,而不是函数来源

(someFunction)() 因为没有附带 base → 普通函数调用 → this = window。

五、结语

通过这个案例,我们看到 this 并不是“跟着函数走的”,而是“跟着调用表达式走的”。一旦你把方法从对象上“拿出来”,它就不属于那个对象了,this 自然也就丢了。理解了这点,就能彻底理解非常多 this 丢失的问题,包括 React、class 绑定、事件回调、计时器、解构赋值、对象方法传递等各种场景。

只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么赋值过程会丢失this
    • 一、场景重现
    • 二、复现问题:同一个函数,不同调用方式
      • 1、问题解答
      • 2、Js中this绑定取决于调用方式
      • 3、为什么赋值表达式会导致 this 的丢失?
    • 三、ECMAScript 规范层面的解释
    • 四、问题总结
    • 五、结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档