如何使用ES2015语法从文件中导入所有已导出的内容?是否有通配符?

49

使用 ES2015 语法,我们有了新的导入语法,我一直在尝试弄清楚如何将一个文件中导出的所有内容无需包装成对象,就可以直接导入到另一个文件中,就好像它们是在同一个文件中定义的。

因此,实际上就是这样:

// constants.js

const MYAPP_BAR = 'bar'
const MYAPP_FOO = 'foo'
// reducers.js

import * from './constants'

console.log(MYAPP_FOO)

根据我的Babel/Webpack设置,这种语法无效。

替代方案

以下方法有效(但如果需要导入多个内容,则很冗长且烦人):

// reducers.js

import { MYAPP_BAR, MYAPP_FOO } from './constants'

console.log(MYAPP_FOO)

这样做也可以(但它将常量包装在对象中):


// reducers.js

import * as consts from './constants'

console.log(consts.MYAPP_FOO)

第一种变量的语法是否存在,还是必须按名称导入每个变量,或者使用包装对象?


2
想象一下如果import * from是可能的。如果reducers.js包含一个变量MYAPP_FOO会发生什么?或者如果另一个模块也包含MYAPP_FOO会怎样?还有很多需要考虑的地方。这不是一个好主意。 - a better oliver
它的缺失确实使得静态分析更容易,因此可以认为使用这种语法是一种反模式。即便如此,偶尔使用它也可能会很方便。 - mikl
5个回答

56

在第一种情况下,您不能通过通配符导入所有变量,因为如果在不同的文件中存在相同名称的变量,则会导致变量冲突。

//a.js
export const MY_VAR = 1;

//b.js
export const MY_VAR = 2;


//index.js
import * from './a.js';
import * from './b.js';

console.log(MY_VAR); // which value should be there?
由于这里无法解析MY_VAR的实际值,因此不可能进行这种类型的导入。
对于您的情况,如果有很多值需要导入,则最好将它们全部导出为对象:
// reducers.js

import * as constants from './constants'

console.log(constants.MYAPP_FOO)

4
通配符导入在Python中可以使用:对a.js的引用被删除,而使用b.js。为什么这在JavaScript中不起作用? - noɥʇʎԀʎzɐɹƆ
2
我也认为这很危险。假设你从几个第三方库中import *。LibA有一个你想要的foo,而LibB没有任何foo。几个月或几年后,LibB添加了一个foo组件,覆盖了LibA的foo。突然间你的代码就崩溃了。LibB甚至可能不认为添加foo是一个semver主要更改,因为它以前不存在。 - error
1
@noɥʇʎԀʎzɐɹƆ 因为你很可能无法控制a.jsb.js的实现,所以你无法防止名称冲突。正如@error所指出的那样,在未来尤其如此。 - almulo
无法理解问题。导入是一个定义。在JavaScript中,重新定义变量为另一个值是完全有效的。如果您两次导入相同的内容,则第二个导入将重新定义第一个。问题出在哪里? - ceving

36

有没有一种语法来表示第一种变体?

没有。

或者你必须按名称导入每个东西,或使用包装对象?

是的。


1
稍微解释一下,可以看看 with - Carl Smith
“with” 完全不相关:它是一个坏主意,因为它依赖于动态值。而“import”是静态的,因此可以定义所有导出名称。请注意 (1)使用动态 import 做这个操作会遇到与“with”相同的问题; (2)重写已导入的名称当然是一个坏主意,但这可能会抛出一个错误,这也有问题,这就是为什么所有这些都没做的原因,但它们比“with”更微妙。 - Eli Barzilay

2

你可以导入对象,迭代其属性,然后使用 eval 手动生成常量,就像这样

import constants from './constants.js'

for (const c in constants) {
  eval(`const ${c} = ${constants[c]}`)
}

不幸的是,由于常量在执行期间动态生成,所以此解决方案无法与我的IDE中的Intellisense一起使用。但总体上应该是有效的。


0

-3
在ES6中,使用以下代码可以在不包装对象的情况下使用导入的内容。
我把它放在这里,为了像我这样的人结束搜索。

constants.js:

export const A = 2;
export const B = 0.01; 
export const C = 0.04;

main.js:

import * as constants from './constants'
const {
    A,
    B,
    C,
} = constants;

7
import * as constants from './constants'import { A, B, C } from './constants' 的较长版本。 - Frederik Krautwald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接