为什么赋值过程会丢失this

目录

为什么赋值过程会丢失this

一、场景重现

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

1、问题解答

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

[3、为什么赋值表达式会导致 this 的丢失?](#3、为什么赋值表达式会导致 this 的丢失?)

[三、ECMAScript 规范层面的解释](#三、ECMAScript 规范层面的解释)

四、问题总结

五、结语


作者: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 绑定、事件回调、计时器、解构赋值、对象方法传递等各种场景。

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

其他热门文章,请关注:

极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

Web Worker:让前端飞起来的隐形引擎

测评:这B班上的值不值?在不同城市过上同等生活水平到底需要多少钱?

通过array.filter()实现数组的数据筛选、数据清洗和链式调用

DeepSeek:全栈开发者视角下的AI革命者

TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

通过MongoDB Atlas 实现语义搜索与 RAG------迈向AI的搜索机制

深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

【前端实战】如何让用户回到上次阅读的位置?

el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题

内存泄漏------海量数据背后隐藏的项目生产环境崩溃风险!如何避免内存泄漏

MutationObserver详解+案例------深入理解 JavaScript 中的 MutationObserver

JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

相关推荐
Mr_sun.12 小时前
Day09——入退管理-入住-2
android·java·开发语言
MAGICIAN...12 小时前
【java-软件设计原则】
java·开发语言
Ticnix12 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人12 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl12 小时前
OpenClaw 深度技术解析
前端
gpfyyds66612 小时前
Python代码练习
开发语言·python
崔庆才丨静觅12 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人13 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼13 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端
盐真卿13 小时前
python第八部分:高级特性(二)
java·开发语言