只是想知道哪个是使用导入的最佳方式:
import * as Foo from './foo';
对:
import { bar, bar2, bar3 } from './foo';
在效率方面,例如,我使用 webpack 来打包所有的 JavaScript 文件。即使我没有在主代码中使用它们,第一个实际上会导入所有内容吗?
我能找到的一些参考资料是:
在 Airbnb 风格指南 中,他们建议不要使用通配符,因此将始终有默认导入对象,并且 this.
如果你使用带有新 uglify 提供的死代码消除的 webpack,或带有 tree-shaking 的 rollupjs,那么未使用的导入将被删除。
我部分同意 airbnb styleguide 不使用通配符导入,尽管 javascripts 通配符导入不会遭受与 pythons 或 javas 通配符导入相同的疾病,即它不会污染其他模块中定义的变量名的范围(你只能通过
moduleB.foo
访问它们,而不是foo
使用import * as moduleB from ...
)。
关于测试的文章:我有点理解这些担忧,但我没有看到那里无法解决的问题。您可以使用一些自定义模块加载器模拟导入本身(自定义 amd 模块加载器实际上是 15 行代码),因此您不必弄乱被测试模块的本地范围。
关于这部分问题:
即使我没有在主代码中使用它们,第一个实际上会导入所有内容吗?
下面是它是如何用 Babel 6.26 编译的:
import { bar, bar2, bar3 } from './foo';
...变成...
'use strict';
var _foo = require('./foo');
import * as Foo from './foo';
...变成...
'use strict';
var _foo = require('./foo');
var Foo = _interopRequireWildcard(_foo);
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key))
newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
}
在这两种情况下,整个文件都是通过
require
导入的。
使用通配符导入,定义了一个
_interopRequireWildcard
函数并用于将所有导出分配给命名空间变量。
值得注意的是,编译后的代码将只包含一个
_interopRequireWildcard
定义,以及一次调用 require
和 _interopRequireWildcard
每次导入。
最终,使用通配符导入将在运行时涉及更多处理,并导致编译后的 js 的大小略有增加。
因为,使用现代 WebPack 设置,两者将生成相同的编译/转译 JS,命名导入的真正价值在于它的表现力。通过命名您的导入,您是在告诉任何打开文件的人,您将使用模块中的哪些功能。这可能有用的一个例子是在编写测试时,如果需要模拟,你有一个明确的导入列表来模拟。
我同意@Tamas。
如果您需要对目标文件中所有导出的完全访问权限,那么您可以使用
import * as Foo from './foo';
或者
import foo from './foo':
但是如果您需要使用特定的函数或 const,那么最好避免“导入 *”并明确说明您需要做什么。