什么时候应该将花括号用于ES6导入?


762

似乎很明显,但是我发现自己对于何时使用花括号在ES6中导入单个模块有些困惑。例如,在我正在从事的React-Native项目中,我具有以下文件及其内容:

initialState.js
var initialState = {
    todo: {
        todos: [
            {id: 1, task: 'Finish Coding', completed: false},
            {id: 2, task: 'Do Laundry', completed: false},
            {id: 2, task: 'Shopping Groceries', completed: false},
        ]
    }
};

export default initialState;

在TodoReducer.js中,我必须不带花括号将其导入:

import initialState from './todoInitialState';

如果将initialState花括号括起来,则以下代码行将出现以下错误:

无法读取未定义的属性待办事项

TodoReducer.js:
export default function todos(state = initialState.todo, action) {
// ...
}

带有花括号的组件也发生类似的错误。我想知道何时应该对单个大括号使用大括号,因为显然,当导入多个组件/模块时,必须将它们括在大括号中,这我知道。

编辑:

此处的SO帖子没有回答我的问题,而是我在询问何时应该或不应该使用大括号来导入单个模块,或者我绝不应该在ES6中使用大括号来导入单个模块(这显然不是情况,如我所见,需要使用花括号将其导入)



1
不,不一样。谢谢
TonyGW '16

Answers:


2260

这是默认导入

// B.js
import A from './A'

仅当A具有默认导出时才有效:

// A.js
export default 42

在这种情况下,导入时分配的名称并不重要:

// B.js
import A from './A'
import MyA from './A'
import Something from './A'

因为它会始终解析到任何的是默认的导出A


这是一个名为import的导入A

import { A } from './A'

仅在A包含名为的命名导出A时才有效:

export const A = 42

在这种情况下,名称很重要,因为您要通过其导出名称来导入特定内容

// B.js
import { A } from './A'
import { myA } from './A' // Doesn't work!
import { Something } from './A' // Doesn't work!

为了使这些工作,你会添加一个对应的命名出口A

// A.js
export const A = 42
export const myA = 43
export const Something = 44

一个模块只能具有一个默认导出,但可以具有任意数量的命名导出(零个,一个,两个或多个)。您可以将它们全部一起导入:

// B.js
import A, { myA, Something } from './A'

在这里,我们将默认导出导入为A,并将导出名称分别命名为myASomething

// A.js
export default 42
export const myA = 43
export const Something = 44

导入时,我们还可以为它们分配所有不同的名称:

// B.js
import X, { myA as myX, Something as XSomething } from './A'

默认导出通常用于通常希望从模块中获取的内容。命名出口通常用于方便的实用程序,但并不总是必需的。但是,由您决定如何导出内容:例如,一个模块可能根本没有默认导出。

这是ES模块的出色指南,解释了默认导出和命名导出之间的区别。


4
使模块具有单独的出口export const myA = 43; export const Something = 44;以及出口是否有任何下降 export default { myA, Something }?因此,当您导入时,您可以import A from './A';为模块中的所有内容提供服务,也 import { Something } from './A';可以仅获取部分模块
Michael

12
很好,但是已经有一种语法可以将所有命名的输出都捕获到一个对象中import * as AllTheThings
丹·阿布拉莫夫

82
解释清楚!我希望我可以对此答案加倍投票。
威拉

7
那- import 'firebase/storage';import 'rxjs/add/operator/map';。那实际上是在做什么?
kyw

9
@kyw:这将执行模块,但忽略导出的值。有用的副作用。
丹·阿布拉莫夫

123

TL; DR:如果要导入非默认导出,请使用大括号。

有关更多详细信息,请参见上面的Dan Abramovs答案。


7
除了提到另一个答案,这个答案还有什么作用?
franksands

6
我先寄去,然后再编辑,不便之处,敬请原谅。
Daniel Schmidt

我并不是想成为一个混蛋,而是试图以最客气的方式来表述它。我只是在徘徊为什么这个答案在这里。
franksands

2
我想这是一个见解,但我发现它很有帮助。我略过上面的答案,这证实了我认为它试图传达的信息。
MORCHARD

84

我要说还有import值得一提的ES6关键字的星号。

在此处输入图片说明

如果您尝试控制台混合日志:

import * as Mix from "./A";
console.log(Mix);

你会得到:

在此处输入图片说明

什么时候应该将花括号用于ES6导入?

当您只需要模块中的特定组件时,括号是金色的,这对于打包器(如webpack)来说占用的空间较小。


4
您的图像是此特定答案的完美备忘单。
Rodrirokr

1
import * as Mix from "./A";import A as Mix from "./A";一样吗?
Shafizadeh

40

上面的Dan Abramov答案解释了有关默认出口命名出口的信息

使用哪个?

引用大卫·赫曼(David Herman):ECMAScript 6支持单一/默认导出样式,并为导入默认值提供了最甜蜜的语法。进口具名出口商品的简洁程度可能甚至应该有所降低。

但是,由于重构,在TypeScript中更喜欢命名为export。例如,如果您默认导出一个类并对其进行重命名,则该类名将仅在该文件中更改,而在其他引用中则不更改,具有命名的导出的类名将在所有引用中重命名。公用事业也首选命名出口。

整体使用您喜欢的任何东西。

额外

默认导出实际上是具有默认名称的命名导出,因此默认导出可以导入为:

import {default as Sample} from '../Sample.js';

2
Additional行是很好的信息。import A from './A'如果您在导出时未定义类似的名称,则没有任何意义export default 42
PGT

8
请确保不要误解David Herman的报价。这并不是说“ 最好在ES6中始终使用单一/默认导出 ”,而是“ 因为单一导出非常普遍,所以ES6最好地支持默认设置,而我们为它们提供了最甜蜜的语法 ”。
Bergi

15

如果您import仅将其视为节点模块,对象和解构的语法糖,我发现它非常直观。

// bar.js
module = {};

module.exports = { 
  functionA: () => {},
  functionB: ()=> {}
};

 // really all that is is this:
 var module = { 
   exports: {
      functionA, functionB
   }
  };

// then, over in foo.js

// the whole exported object: 
var fump = require('./bar.js'); //= { functionA, functionB }
// or
import fump from './bar' // same thing, object functionA and functionB props


// just one prop of the object
var fump = require('./bar.js').functionA;

// same as this, right?
var fump = { functionA, functionB }.functionA;

// and if we use es6 destructuring: 
var { functionA } =  { functionA, functionB };
// we get same result

// so, in import syntax:
import { functionA } from './bar';

9

为了理解import语句中花括号的用法,首先,您必须了解ES6中引入的销毁概念。

  1. 对象解构

    var bodyBuilder = {
      firstname: 'Kai',
      lastname: 'Greene',
      nickname: 'The Predator'
    };
    
    var {firstname, lastname} = bodyBuilder;
    console.log(firstname, lastname); //Kai Greene
    
    firstname = 'Morgan';
    lastname = 'Aste';
    
    console.log(firstname, lastname); // Morgan Aste
  2. 阵列解构

    var [firstGame] = ['Gran Turismo', 'Burnout', 'GTA'];
    
    console.log(firstGame); // Gran Turismo

    使用列表匹配

      var [,secondGame] = ['Gran Turismo', 'Burnout', 'GTA'];
      console.log(secondGame); // Burnout

    使用价差运算符

    var [firstGame, ...rest] = ['Gran Turismo', 'Burnout', 'GTA'];
    console.log(firstGame);// Gran Turismo
    console.log(rest);// ['Burnout', 'GTA'];

现在,我们已经在ES6中解决了这个问题您可以导出多个模块。然后,您可以像下面那样利用对象分解

假设您有一个名为 module.js

    export const printFirstname(firstname) => console.log(firstname);
    export const printLastname(lastname) => console.log(lastname);

您想将导出的函数导入到index.js;中。

    import {printFirstname, printLastname} from './module.js'

    printFirstname('Taylor');
    printLastname('Swift');

您也可以像这样使用不同的变量名

    import {printFirstname as pFname, printLastname as pLname} from './module.js'

    pFname('Taylor');
    pLanme('Swift');

由于您正在显示对销毁的比较,因此我将在您的最后评论中添加等效的销毁比较: import {printFirstname as pFname, printLastname as pLname} from './module.js'等效于:var foo = {printFirstname: 'p_f_n', printLastname: 'p_l_n'}; var { printFirstname:pFname, printLastname: pLname } = foo; pFname('Taylor'); pLname('Swift');
Adam Moisa

健美迷?
Tushar Pandey

@TusharPandey我是健美者
–Typan

1
我认为在任何有关导入以及何时使用卷发与何时不使用卷发的解释中,如果您没有提到对象破坏,那么您实际上并没有给出最好的解释。一旦了解了销毁功能,我就再也没想过为什么要使用卷曲了,这在直觉上是有意义的。
Eric Bishard

6

摘要ES6模块:

出口:

您有两种出口类型:

  1. 命名出口
  2. 默认导出,每个模块最多1个

句法:

// Module A
export const importantData_1 = 1;
export const importantData_2 = 2;
export default function foo () {}

进口:

型出口(即命名或默认出口)影响如何进口的东西:

  1. 对于命名导出,我们必须使用花括号并将确切的名称用作导出的声明(即变量,函数或类)。
  2. 对于默认导出,我们可以选择名称。

句法:

// Module B, imports from module A which is located in the same directory

import { importantData_1 , importantData_2  } from './A';  // for our named imports

// syntax single named import: 
// import { importantData_1 } 

// for our default export (foo), the name choice is arbitrary
import ourFunction from './A';   

有趣的事情:

  1. 在大括号内使用逗号分隔的列表,并导出的匹配名称进行命名导出。
  2. 使用您选择的不带花括号的名称进行默​​认导出。

别名:

每当您想重命名已命名的导入时,都可以通过别名来实现。语法如下:

import { importantData_1 as myData } from './A';

现在我们已经导入了,importantData_1 但是标识符myData不是importantData_1


5

通常,在导出函数时,您需要使用{}

if you have export const x 

你用 import {x} from ''

if you use export default const x 

您需要在import X from '' 这里使用,您可以将X更改为所需的任何变量




0

对于默认导出,我们在导入时不使用{}。

例如

player.js

export default vx;

index.js

import vx from './player';

index.js 在此处输入图片说明

player.js 在此处输入图片说明

如果要导入导出的所有内容,则使用* 在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.