在node.js(ES6 / Babel)中,import X和import * as X之间有什么区别?

55

我有一个使用ES6编写(使用Babel编译)的node.js库lib,其中我导出了以下子模块:

"use strict";

import * as _config from './config';
import * as _db from './db';
import * as _storage from './storage';

export var config = _config;
export var db = _db;
export var storage = _storage;
如果我想在我的主项目中引入这个库,就像这样:
import * as lib from 'lib';
console.log(lib);

我可以看到正确的输出并且它按预期工作{ config: ... }。然而,如果我尝试像这样包含库:

import lib from 'lib';
console.log(lib);

它将是undefined

有人能解释一下这里发生了什么吗?这两种导入方法不应该是等效的吗?如果不是,我错过了什么区别?

3个回答

80
import * as lib from 'lib';

请求一个具有'lib'中所有命名导出项的对象。


export var config = _config;
export var db = _db;
export var storage = _storage;

是被命名出口,这就是为什么你最终得到了像你所做的那样的对象。


import lib from 'lib';

需要的是lib模块的default导出。


例如:

export default 4;

这会使lib === 4。它不会提取命名导出项。若要从默认导出项获取对象,您必须显式执行。

export default {
  config: _config,
  db: _db,
  storage: _storage
};

19

因为理解了使用括号、星号和不使用它们的导入方式,所以我补充一下Logan的解决方案,这帮我解决了一个问题。

import * as lib from 'lib';

相当于:

import {config, db, storage} as lib from 'lib';

在这里,* 类似于一个通配符,导入了 lib 中所有的 export var

export var config;
export var db;
export var storage;

或者,使用:

import lib from 'lib';

允许您仅访问默认导出:

// lib.js
export default storage;

使用 {} 还可以从模块中仅导入特定组件,这样可以在像 Webpack 这样的打包工具中减小文件体积。

然而:

import storage, { config, db } from './lib'

会导入所有模块,包括export default storage;

可参考 Dan Abramov 的回答:When should I use curly braces for ES6 import?


4
只是没有 import {…} as … from … 的语法。 - Bergi
修改了。你是对的,没有用于{...}的扩展运算符,我应该使用等等代替。 - tgrrr
当然,由于这不是对象字面量/解构,因此没有扩展/剩余语法。但是,在导入中仍然没有{…} as …的语法,因此“与...相同”是无意义的。(我认为你的意思不是“产生与...相同的语法错误”) - Bergi
没错。为了更清晰,更新了答案。我使用了“is the same as”,因为较小的词更易于理解。我将其改为“equivalent of”以使其更具体。 - tgrrr
1
但是你能解释一下 import {config, db, storage} as lib from 'lib'; 是什么意思吗?它在任何地方都没有描述。 - Bergi

4

import X from Y; 是一种语法糖。

import lib from 'lib';

等同于

import { default as lib } from 'lib';


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