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

通配符或星号(*)与命名或选择性导入es6 javascript,javascript,import,ecmascript-6,wildcard,es6-modules,Javascript,Import,Ecmascript 6,Wildcard,Es6 Modules,只是想知道使用导入的最佳方式是: import*作为来自'/Foo'的Foo VS: 从'/foo'导入{bar,bar2,bar3} 就效率而言,比如说,我使用webpack捆绑所有JavaScript文件。即使我没有在主代码中使用它们,第一个是否会真正导入所有内容 我可以找到一些参考资料: 在中,他们建议不使用通配符,因此将始终存在默认的导入对象。如果您使用带有新uglify提供的死代码消除功能的webpack,或带有树抖动功能的rollupjs,则未使用的导入将被剥离 我部分同意airbn

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

import*作为来自'/Foo'的Foo

VS:

从'/foo'导入{bar,bar2,bar3}

就效率而言,比如说,我使用webpack捆绑所有JavaScript文件。即使我没有在主代码中使用它们,第一个是否会真正导入所有内容

我可以找到一些参考资料:


在中,他们建议不使用通配符,因此将始终存在默认的导入对象。

如果您使用带有新uglify提供的死代码消除功能的webpack,或带有树抖动功能的rollupjs,则未使用的导入将被剥离

我部分同意airbnb styleguide不使用通配符导入,尽管javascripts通配符导入不会遭受与pythons或javas通配符导入相同的疾病,即它不会污染其他模块中定义的变量名称的范围(您只能通过
moduleB.foo
访问它们,在使用
import*as moduleB from…
时,不能通过
foo
访问它们)

关于关于测试的文章:我有点理解这些问题,但我认为没有什么是无法解决的。你可以用一些自定义模块加载器(自定义amd模块加载器实际上是15行代码)来模拟导入本身,这样你就不必弄乱被测模块的本地范围。

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


但是,如果您需要使用特定的函数或常量,那么最好避免“导入*”,并明确您需要执行的操作。

关于问题的这一部分:

即使我没有在主代码中使用它们,第一个是否会真正导入所有内容

以下是使用Babel 6.26编译的过程:

命名 …变成

'use strict';

var _foo = require('./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;
    }
}

通配符 …变成

'use strict';

var _foo = require('./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
导入的

通过通配符导入,定义了一个
\u interopRequireWildcard
函数,用于将所有导出分配给名称空间变量

值得注意的是,编译后的代码只包含一个
\u interopRequireWildcard
定义,以及每次导入时对
require
\u interopRequireWildcard
的一个调用


最终,通配符导入的使用将在运行时涉及更多的处理,并导致编译后的js的大小略有增加。

因为,使用现代的WebPack设置,两者将生成相同的编译/传输js,命名导入的真正价值在于它的表现力有多强。通过命名导入,你就知道了任何一个打开的文件都可以从您将要使用的模块中运行。例如,在编写测试时,如果需要模拟,您将有一个要模拟的导入的显式列表。如果我
import*作为Foo from./Foo'
,并且我只使用
Foo.bar
,那么
Foo.bar2
Foo.bar3
是否会被作为死代码删除?@bsapaka是的,如果
Foo.bar2
Foo.bar3
根本没有使用。我在哪里可以阅读更多关于这方面的信息?例如,官方文档或github发行线程。可能重复