【问题标题】:When should I use curly braces for ES6 import?什么时候应该使用花括号进行 ES6 导入?
【发布时间】:2016-08-16 04:51:25
【问题描述】:

这似乎很明显,但我发现自己对何时使用花括号在 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 括在花括号中,则以下代码行会出现以下错误:

无法读取未定义的属性 todo

文件TodoReducer.js

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

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

here 的 Stack Overflow 帖子没有回答我的问题,而是我问什么时候我应该或不应该使用花括号来导入 single 模块,或者我不应该在 ES6 中使用花括号来导入单个模块(这显然不是这种情况,因为我已经看到需要花括号的单个导入)。

【问题讨论】:

标签: javascript import ecmascript-6


【解决方案1】:

这是一个默认导入

// 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默认导出


这是一个名为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'

默认导出往往用于您通常希望从模块中获得的任何内容。命名的导出往往用于可能很方便但并不总是必需的实用程序。但是,您可以选择如何导出内容:例如,一个模块可能根本没有默认导出。

This is a great guide to ES modules, explaining the difference between default and named exports.

【讨论】:

  • 让一个模块有单独的导出 export const myA = 43; export const Something = 44;export default { myA, Something } 有什么坏处吗?因此,当您导入时,您可以import A from './A'; 获取模块中的所有内容,或者import { Something } from './A';,这样您只会获得模块中的一部分
  • 很好,但是已经有一种语法可以将所有命名的导出抓取到一个对象中:import * as AllTheThings
  • 这个怎么样 - import 'firebase/storage';import 'rxjs/add/operator/map';。那实际上是在做什么?
  • @kyw:这会执行模块但忽略导出的值。对副作用有用。
  • 注意:当您执行 const A = 42; export default A; 时,您不能执行 import { A }; 这可能看起来很奇怪,并且在从命名导出重构为默认导出时可能会破坏您的导入(除非您删除花括号)。我想这有点合乎逻辑(叹气..),因为默认导出只导出一个值,而不是一个名称。 export default A 仅指 42 引用的值 A
【解决方案2】:

我想说import ES6 关键字还有一个星号符号值得一提。

如果您尝试控制台记录 Mix:

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

你会得到:

什么时候应该使用花括号进行 ES6 导入?

当您只需要模块中的特定组件时,括号是金色的,这使得 webpack 之类的打包器占用的空间更小。

【讨论】:

  • import * as Mix from "./A";import A as Mix from "./A"; 一样吗?
  • 你所说的“加星标”是什么意思? Wild cards?
  • @PeterMortensen term star, or starred 我相信我用了“*”thefreedictionary.com/starred 一个星号。那是 3 年前的事了,但我认为是这样。
  • @PeterMortensen 加星标表示使用开始符号并从该文件/模块导入所有内容
【解决方案3】:

Dan Abramov's answer 解释了默认导出命名导出

使用哪个?

引用 David HermanECMAScript 6 支持单一/默认导出样式,并为导入默认值提供了最甜美的语法。导入命名导出可以甚至应该稍微不那么简洁。

但是,在 TypeScript 中,由于重构,命名导出受到青睐。例如,如果您默认导出一个类并重命名它,则类名将仅在该文件中更改,而在其他引用中不会更改,命名为导出的类名将在所有引用中重命名。 命名导出也是实用程序的首选。

总体使用你喜欢的任何东西。

附加

默认导出实际上是一个名为default的命名导出,所以默认导出可以导入为:

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

【讨论】:

  • Additional 行是很好的信息。如果您在没有定义像 export default 42 这样的名称的情况下导出,import A from './A' 没有意义。
  • 请确保不要误解大卫赫尔曼的报价。这并不意味着“倾向于总是在 ES6 中使用单一/默认导出”,而是“因为单一导出如此普遍,ES6 最好支持默认值我们给了他们最甜蜜的语法".
【解决方案4】:

如果您认为 import 只是 Node.js 模块、对象和 destructuring 的语法糖,我觉得它非常直观。

// 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' // The same thing - object functionA and functionB properties


// Just one property 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';

【讨论】:

    【解决方案5】:

    总结ES6模块:

    出口:

    您有两种类型的导出:

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

    语法:

    // 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. 使用您选择的不带花括号的名称进行默​​认导出。

    别名:

    当您想要重命名命名导入时,可以通过aliases 来实现。其语法如下:

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

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

    【讨论】:

      【解决方案6】:

      要想了解import语句中花括号的使用,首先要了解ES6中引入的destructuring的概念

      >
      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');
      • 健美爱好者?
      • @TusharPandey 我是一名健美运动员
      • 我认为在任何关于导入以及何时使用 curlys 与不使用它们的解释中,如果你没有提到对象破坏,那么你真的没有给出最好的解释。一旦我了解了解构,我就再也没有想过为什么要使用 curly,它只是直观地有意义。
      【解决方案7】:

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

      如果你有

      export const x
      

      你使用

      import {x} from ''
      

      如果你使用

      export default const x
      

      你需要使用

      import x from ''
      

      您可以在此处将 X 更改为您想要的任何变量。

      【讨论】:

        【解决方案8】:

        花括号 ({}) 用于导入命名绑定,其背后的概念是 destructuring assignment

        关于 import 语句如何与示例一起工作的简单演示可以在我自己对 When do we use '{ }' in javascript imports? 的类似问题的回答中找到。

        【讨论】:

          【解决方案9】:

          大括号仅在命名导出时用于导入。如果导出为默认值,则不使用花括号进行导入。

          【讨论】:

            【解决方案10】:

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

            例如,

            文件 player.js

            export default vx;
            

            文件 index.js

            import vx from './player';
            

            文件 index.js

            文件 player.js

            如果我们想导入我们导出的所有内容,那么我们使用*

            【讨论】:

              【解决方案11】:

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2018-10-13
                • 2022-11-10
                相关资源
                最近更新 更多