上边这行代码是解构吗?只能说像,是吧。
我们再来看看 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 语法:模块导入和解构赋值。
它们看起来很像,但实际上有本质的区别。
模块导入是一种符号绑定,它只是给导入的内容取了一个别名,而不会创建新的变量或内存空间。
解构赋值是一种赋值简写,它会创建新的变量,并将对象的属性值拷贝过来。
造成混淆的原因就是平时积累知识的时候,出现了大量不准确的认知共同造成的。
那么你要突破这个瓶颈,必须要重塑自己的认知,往小的说就是这样小的知识点,往大了说是整个前端的原理和概念,都要进行重塑,所以未来道路我们一起前行吧!
如果你有什么问题或建议,请在评论区留言,如果你觉得这篇文章有用,请点赞收藏或分享给你的朋友!