通配符或星号(*)与命名或选择性导入 es6 javascript

只是想知道哪一种是使用 import 的最佳方式:

import * as Foo from './foo';

VS:

import { bar, bar2, bar3 } from './foo';

在效率方面,例如,我使用 webpack 来捆绑所有的 JavaScript 文件。即使我没有在主代码中使用它们,第一个会实际导入所有内容吗?

我能找到的一些参考资料是:

Airbnb 风格指南中,他们推荐不使用通配符,因此总是有默认的导入对象和 这个

51642 次浏览

如果你使用 webpack 和新的 uglify 提供的死码删除,或者 rollupjs 和摇树,那么未使用的导入将被删除。

我部分同意 airbnb 样式指南不使用通配符导入,尽管 javascript 通配符导入不会像 python 或 javas 通配符导入那样引发疾病,即它不会使用其他模块中定义的变量名污染范围(当使用 import * as moduleB from ...时,只能通过 moduleB.foo而不是 foo访问它们)。

关于这篇关于测试的文章: 我有点理解这些担忧,但是我没有看到任何无法解决的问题。您可以使用一些自定义模块加载器来模拟导入本身(一个自定义 amd 模块加载器实际上是15行代码) ,因此您不必干扰测试模块的本地作用域。

我同意@Tamas。
如果需要完全访问目标文件中的所有导出,则可以使用 import * as Foo from './foo'; 或者 import foo from './foo':

但是如果您需要使用特定的函数或常量,那么最好避免使用“ import *”,并明确说明您需要做什么。

关于问题的这一部分:

即使我没有在主代码中使用它们,第一个会实际导入所有内容吗?

下面是如何用 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,因此命名导入的真正价值在于它的表达能力。通过命名您的导入,您可以告诉任何打开文件的人您将使用的模块中的哪些函数。例如,在编写测试时,如果有必要进行模仿,那么可以使用一个显式的导入列表来进行模仿。