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

时间:2017-02-05 11:36:33

标签: javascript import ecmascript-6 wildcard es6-modules

只是想知道哪一个是使用导入的最佳方式:

import * as Foo from './foo';

VS

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

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

我能找到的一些参考文献是:

Airbnb style guide中,他们建议不要使用通配符,因此始终会有默认导入对象和this

4 个答案:

答案 0 :(得分:16)

如果您使用带有新uglify提供的死代码消除的webpack,或者使用树状抖动的rollupjs,那么将删除未使用的导入。

我部分同意airbnb样式指南不使用通配符导入,尽管javascripts通配符导入不会遇到与pythons或javas通配符导入相同的疾病,即它不会使用其他定义的变量名来污染范围模块(使用moduleB.foo时,您只能foo访问它们,而不是import * as moduleB from ...

关于测试的文章:我很了解这些问题,但我看不出那里无法解决的问题。您可以使用一些自定义模块加载器来模拟导入(自定义模块加载器实际上是15行代码),因此您不必弄乱测试模块的本地范围。

答案 1 :(得分:11)

关于这部分问题:

  

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

以下是使用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的大小略有增加。

答案 2 :(得分:4)

我同意@Tamas 如果您需要对目标文件中的所有导出的完全访问权限,则可以使用<div class="all"> <div class="header">All</div> <div class="cell-1"></div> <div class="cell-2"></div> <div class="cell-3"></div> <div class="cell-4"></div> </div> <div class="first"> <div class="header">First</div> <div class="cell-1"></div> <div class="cell-2"></div> <div class="cell-3"></div> <div class="cell-4"></div> </div> <div class="second"> <div class="header">Second</div> <div class="cell-1"></div> <div class="cell-2"></div> <div class="cell-3"></div> <div class="cell-4"></div> </div> <div class="third"> <div class="header">Third</div> <div class="cell-1"></div> <div class="cell-2"></div> <div class="cell-3"></div> <div class="cell-4"></div> </div> 要么 import * as Foo from './foo';

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

答案 3 :(得分:0)

由于使用现代WebPack设置,两者将生成相同的编译/转换JS,命名导入的真正价值在于它的表现力。通过命名您的导入,您可以告诉任何一个打开文件的文件,该文件的功能来自您将要使用的模块。这可能有用的一个示例是在编写测​​试时,如果需要进行模拟,则您有一个明确的模拟导入列表。