今天子辰和大家探讨分析一个非常容易混淆的概念,理清这个问题,才能说明你对技术的理解真正到了一定的水平。
“上边这行代码是解构吗?”
只能说像,是吧。
我们再来看看 module.mjs 写了什么。
module.mjs 里导出了一个 n 和一个 increase 函数,就相当于导出了一个对象。
然后再 index.mjs 解构这个对象,拿到 n 和 increase 这两个属性。
打印出来的结果也没什么问题,就是一个 1 和一个函数。
这的确无比得像是一个解构,但是像并不意味着就是。
我们来继续研究研究,用解构的写法写一遍。
可以发现打印出来的结果是一样的,那是不是就是等价的呢?
我们来使用一下这两个属性看看有什么不同。
可以看到使用解构的方式输出的是两个 1。
那我们在 index.mjs 也使用同样的方式试试。
打印出来就变成了 1 和 2 了。
所以 index.mjs 里根本不是解构。
要解释清楚这个问题,我们就要先解释一下 _module.js 中的代码。
什么叫做解构?解构的英文全称叫做 Destructuring assignment,assignment 就是赋值的意思。
解构就是在赋值,它是赋值的一种简写而已,意味着这个 obj 里的两个属性
- 一个 n 是值类型。
- 一个 increase 是一个引用类型,它地址指向一个函数。
解构就意味着把这个属性值 n 的值 1,赋值给一个变量 n,它的值是拷贝过来的,那么就意味着同时存在两块内存空间,一个是对象obj 的 n,一个是变量 n。
increase 也是一样的,它存的是一个地址,把这个地址拷贝过来形成一个变量 increase,也是两块内存空间,只不过地址指向的是同一个函数。
那么当我们去调用 increase 的时候,它变化的是 obj 对象里的 n,跟变量 n 就没有关系了。
所以我们看到 _module.js 的输出结果是两个 1。
而 index.mjs 之所以不行,因为它就不是解构,它叫做符号绑定,英文全称叫做 Live bindings。
看了这张图你会发现和解构那张图有一个巨大的变化,n 和 increase 压根没有自己的内存空间,只是有一个名字而已。
也就是说我们使用具名导入的时候,实际上就是给导出的东西取了一个名字,它们用的内存空间还是模块内部的内存空间。
这就意味着当我们去调用 increase 的时候,改变 n 的值时,我们导入的 n 也是会收到影响的。
所以再也不能把具名导入称之为解构了。
总结
子辰介绍了一种常见而容易混淆的 JS 语法:模块导入和解构赋值。
它们看起来很像,但实际上有本质的区别:
模块导入是一种符号绑定,它只是给导入的内容取了一个别名,而不会创建新的变量或内存空间。
解构赋值是一种赋值简写,它会创建新的变量,并将对象的属性值拷贝过来。
造成混淆的原因就是平时积累知识的时候,出现了大量不准确的认知共同造成的。
那么你要突破这个瓶颈,必须要重塑自己的认知,往小说就是像这样的小的知识点,请关注子辰的掘金账号,类似的内容我每日都会分享。
而往大了说,你需要重塑的可能是整个前端的原理和概念,至少像以下这些前端的重要知识点,都要进行重塑。
- 事件循环
- V8引擎原理
- 浏览器渲染原理
- 互联网企业项目
- Vue响应式源码
如果你想搞定的是上面这些内容,也欢迎加入渡一一起学习,可以通过主页联系我哦
参考资料
- 《渡一web前端大师课》 袁进