对 ES6 模块有些陌生,发现自己在以下 2 种模式之间左右为难......
模式 #1 -
import
上的解构
import { func1, func2, func3 } from 'my-funcs';
模式 #2 -
const
上的解构
import * as myFuncs from 'my-funcs';
const { func1, func2, func3 } = myFuncs;
我喜欢模式#1,因为它简洁,但我也喜欢模式#2,因为它看起来更明确。
这些方法之间有什么区别(如果有的话)?
在 ES6 中,导入绑定到变量(而不是值)。这意味着,如果导出模块更改其导出的变量,则更新后的值将反映在导入它的所有模块中。
例如,假设我们有一个模块,它导出一个原始值,然后在一段未指定的时间段后更改它。
myVar.js
export var myVar = "1";
setTimeout(() => {myVar = "2"}, 2000);
假设你像这样导入它:
main1.js
import { myVar } from './myVar.js';
console.log(myVar);
setTimeout(() => { console.log(myVar); }, 3000);
输出将是:
1
2
但是,如果您在导入变量后立即将原始值分配给变量,则该值将保持不变。
main2.js
import * as MyVar from './myVar.js';
const myVar = MyVar.myVar;
console.log(myVar);
setTimeout(() => { console.log(myVar); }, 3000);
该程序的输出将是:
1
1
您可能需要记住这种差异。
第一个不是解构,而是将命名导出导入到模块范围中。第二个确实以名称
myFuncs
导入模块命名空间对象,然后对其进行解构。
主要区别在于,在第二种模式中,您拥有常量,而不是对导出绑定的直接引用(可能会发生变化)。这很重要,例如用于循环依赖。
一个微小的区别是附加标识符
myFuncs
,这是相当无用的。然而,它确实使您可以访问模块的所有导出,这对于 tree-shaking 很重要 - 如果您显式仅导入模块的一部分,则捆绑器可能会产生较小的结果。
有充分的理由使用其中一种而不是另一种吗?
当然 - 第一个模式更简单、更短,在边缘情况下可以正常工作,并且可以更好地优化。