Promise/A+ 规范:引用不可变 + 核心术语(对象 / 函数)详解
Promise/A 规范引用不可变 核心术语对象 / 函数详解文章目录Promise/A 规范引用不可变 核心术语对象 / 函数详解前言一、“引用不可变” 是什么意思二、为什么要强调 “引用不可变”三、代码示例3.1 正确情况Promise 引用不可变实际运行效果3.2 错误假设如果 Promise 引用可变会炸四、解释术语中的“对象或函数”4.1 先搞懂 JavaScript 里「函数」和「对象」的关系4.2 为什么 Promise 定义成「对象或函数」4.3 为什么 Thenable 也定义成「对象或函数」4.4 核心术语对照表优化版术语补充说明总结前言在 Promise/A 规范的核心术语中有两个非常关键、但容易被忽略的细节一是异步结果的「引用不可变」二是规范定义中「Promise / Thenable 是对象或函数」。很多开发者知道 Promise 状态一旦确定就不能修改却不清楚“引用不可变”到底是什么意思也有很多人疑惑为什么规范要写「对象或函数」函数为什么也算在内本文把这两个知识点彻底讲透帮你真正理解 Promise 底层规范写出更严谨、可靠的异步代码。一、“引用不可变” 是什么意思在 JavaScript 里引用不可变指的是当 Promise 被决议成功 / 失败后它的value成功结果或reason失败原因一旦确定就永远不会再改变。用去判断这个值的引用结果永远是true不会因为后续代码而变化。注意这里说的是引用本身不可变不是指值的内部属性不可修改。如果value是一个对象 / 数组你依然可以修改它的属性 / 元素但 Promise 永远不会把这个value替换成另一个全新的对象 / 值。例如对象类型的 value内部属性可以改但引用本身也就是它在内存中的 “身份”永远不变Promise 也不会把它替换成一个全新的值。constobj{name:Alice};constpPromise.resolve(obj);p.then(val{val.nameBob;// ✅ 可以修改对象内部属性console.log(valobj);// true → 引用没变});// 一旦 p Promise.resolve(obj) 决议完成就永远无法让 p 再 resolve 成另一个全新对象比如 { name: Charlie }只能修改现有对象的属性。例如数组版示例内部可改引用不变// 1. 创建一个数组constarr[10,20,30];// 2. 用这个数组创建 PromiseconstpPromise.resolve(arr);p.then(val{// ✅ 可以修改数组内部的元素、push、pop 都行val.push(40);val[0]999;console.log(val);// 输出[999, 20, 30, 40]console.log(valarr);// true → 引用完全没变});// 重点// 你永远不能让 p 再变成另一个全新的数组// 引用永远锁定不会变通俗来讲引用不可变 房子地址永远不变修改属性 / 元素 装修房子、换家具。房子还是那栋房子引用不变只是里面东西变了内容可变。二、为什么要强调 “引用不可变”核心目的是为了保证异步编程的可靠性与可预测性主要有这几点避免竞态与数据不一致Promise 可以被多个.then()同时监听如果决议后还能被篡改不同回调可能拿到不同版本的值导致逻辑混乱、难以调试。引用不可变让所有回调都看到同一个结果行为稳定可预期。符合 “一次性决议” 的核心设计Promise 只能从pending → fulfilled/rejected状态不可逆。既然状态不可逆承载结果的value/reason也必须是一次性确定的否则就违背了 “决议后不再变化” 的契约。方便缓存与共享因为引用不变你可以安全地把 Promise 或它的结果缓存、传递给多处使用不用担心别人偷偷修改结果降低了代码的耦合与风险。与 JavaScript 语言特性对齐JS 中是判断引用是否相同的核心运算符强调 “判定不变”就是明确告诉开发者这个值的身份标识是稳定的不会在决议后被替换成新对象避免了引用变化带来的隐蔽 Bug。一句话总结“引用不可变” Promise 决议后它的结果值 / 失败原因永远不会被整体替换只能在内部修改如果是对象 / 数组所有监听这个 Promise 的回调都会看到同一个引用。这么做是为了让异步代码更稳定、可预测、易维护 。三、代码示例下面用两段极简代码让你一眼看懂什么是 Promise 引用不可变以及如果可变会出现什么灾难。3.1 正确情况Promise 引用不可变实际运行效果// 1. 创建一个对象constperson{name:小明};// 2. 用这个对象创建 PromiseconstpromisePromise.resolve(person);// 3. 监听结果promise.then((res){console.log(第一次拿到结果,res);// { name: 小明 }console.log(引用是否相同,resperson);// true ✔️});// 4. 尝试修改 person 的属性允许person.name小红;// 5. 再次监听同一个 Promisepromise.then((res){console.log(第二次拿到结果,res);// { name: 小红 }console.log(引用依然相同,resperson);// true ✔️});// 关键永远无法把 promise 的结果改成【另一个全新对象】// promise 决议后引用永远不变结论引用不可变 这个意思对象内部可以改引用本身永远不会被替换成新对象所有.then()拿到的永远是同一个引用3.2 错误假设如果 Promise 引用可变会炸// 模拟一个“坏 Promise”结果可以被随便改letbadResult{name:初始值};constbadPromise{then:(cb)cb(badResult),};// 第一次监听badPromise.then((res){console.log(A 组件拿到,res.name);// 初始值});// 中途被别人篡改结果badResult{name:被恶意修改了};// 引用直接变了// 第二次监听badPromise.then((res){console.log(B 组件拿到,res.name);// 被恶意修改了});后果不同时间、不同组件拿到完全不一样的值异步逻辑彻底混乱无法调试、无法信任、无法缓存四、解释术语中的“对象或函数”为什么规范里写「对象或函数」这是 ECMAScript 官方规范的严谨写法不是笔误也不是多余。下面我们彻底讲透4.1 先搞懂 JavaScript 里「函数」和「对象」的关系在 JS 里函数本质上是「可调用的对象」所有函数都是 Function 构造函数的实例而 Function 继承自 Object所以函数 ≠ 普通对象但函数「是对象」同时拥有对象的所有特性验证typeof Promise functiontypeof new Promise((){}) object4.2 为什么 Promise 定义成「对象或函数」① 「对象」覆盖我们日常用的 Promise 实例这是 99% 的开发场景我们通过 new Promise() 创建的实例 p就是一个对象它有.then()方法完全符合 Promise 规范。constpnewPromise(resolveresolve(1));console.log(typeofp);// object② 「函数」覆盖 Promise 构造函数本身Promise 本身是一个构造函数规范必须把「函数」写进去才能保证Promise 构造函数本身也符合 Promise 的定义虽然我们几乎不会直接调用 Promise.then()但从规范严谨性上必须覆盖这个特例。console.log(typeofPromise);// function4.3 为什么 Thenable 也定义成「对象或函数」核心逻辑Thenable 是「类 Promise 对象」是 Promise 规范的「超集」只要一个东西不管是对象还是函数有 .then() 方法就属于 Thenable目的是为了互操作性让非标准 Promise比如 jQuery 的 Deferred、自定义异步对象能和标准 Promise 无缝兼容比如你可以把一个自定义的「有 then 方法的函数」传给Promise.resolve()它会被当成 Promise 处理代码验证对象 / 函数两种形式:// 1. 普通对象形式的 ThenableconstthenableObj{then(resolve){resolve(1);}};Promise.resolve(thenableObj).then(vconsole.log(v));// 1// 2. 函数形式的 Thenable符合规范定义functionthenableFn(){}thenableFn.thenfunction(resolve){resolve(2);};Promise.resolve(thenableFn).then(vconsole.log(v));// 24.4 核心术语对照表优化版术语规范定义通俗理解Promise一个对象或函数包含一个then方法且该方法的行为符合 ECMAScript Promise 规范标准异步结果的容器。日常开发中它是我们通过new Promise()创建的对象但从规范严谨角度Promise构造函数本身是函数。核心特征是拥有.then()方法。Thenable一个定义了then方法的对象或函数类 Promise 对象 (Promise-like)。它不是标准 Promise但只要具备.then()方法就能被标准 Promise 处理核心作用是实现非标准异步对象与标准 Promise 的互操作。术语补充说明以下两点帮你彻底理解「为什么包含函数」Promise 包含「函数」的原因在 JS 中函数是一种特殊的可执行对象。规范写「对象或函数」是为了覆盖Promise 构造函数typeof Promise function这一特例确保定义的严谨性日常场景虽只用到实例对象但规范必须完整。Thenable 包含「函数」的原因这里的「函数」指代任何挂载了then方法的自定义函数。只要满足「有 then 方法」这一条件标准 Promise 就能将其视为类 Promise 对象进行解析实现跨库 / 跨框架的异步兼容。总结引用不可变Promise 一旦决议成功 / 失败它的结果 value / 失败原因 reason 的引用永远不变。你可以修改对象/数组内部属性但不能替换成全新的引用保证异步结果稳定、可预测、可缓存。核心术语对象或函数Promise 是对象或函数是标准异步容器拥有符合规范的 then 方法。Thenable 是拥有 then 方法的对象或函数用于实现 Promise 互操作性。函数之所以被包含是因为 JS 中函数是特殊对象且 Promise 构造函数本身就是 function。理解这两点是吃透 Promise/A 规范、掌握异步底层逻辑的关键一步。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2483122.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!