Когда я должен использовать фигурные скобки для импорта ES6?

767

Это кажется очевидным, но я был немного озадачен тем, когда использовать фигурные скобки для импорта одного модуля в 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 из undefined

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

Подобные ошибки также случаются с моими компонентами с помощью фигурных скобок. Мне было интересно, когда я должен использовать фигурные скобки для одного импорта, потому что, очевидно, при импорте нескольких компонентов / модулей, вы должны заключить их в фигурные скобки, что я знаю.

Редактировать:

Сообщение SO здесь не отвечает на мой вопрос, вместо этого я спрашиваю, когда я должен или не должен использовать фигурные скобки для импорта одного модуля, или я никогда не должен использовать фигурные скобки для импорта одного модуля в ES6 (это, очевидно, не случай, как я видел один импорт с фигурными скобками требуется)

TonyGW
источник

Ответы:

2274

Это импорт по умолчанию :

// 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, а именованные экспорты называются myAи Something, соответственно.

// 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';вы получите только часть модуля
Майкл
12
Это прекрасно, но есть уже синтаксис для захвата всех именованного экспорта в единый объект: import * as AllTheThings.
Дан Абрамов
82
Четко объяснил! Я бы хотел удвоить голосование за этот ответ.
Вилла
7
насчет this- import 'firebase/storage';или import 'rxjs/add/operator/map';. Что это на самом деле делает?
Kyw
9
@kyw: при этом выполняется модуль, но игнорируется экспортированное значение. Полезно для побочных эффектов.
Дан Абрамов
84

Я бы сказал, что есть importключевое слово для ключевого слова ES6, которое стоит упомянуть.

введите описание изображения здесь

Если вы пытаетесь консоль журнала Mix:

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

Ты получишь:

введите описание изображения здесь

Когда я должен использовать фигурные скобки для импорта ES6?

Скобки золотые, когда вам нужны только определенные компоненты из модуля, что делает меньшие следы для упаковщиков, таких как веб-пакет.

прости
источник
4
Ваше изображение является идеальной шпаргалкой для этого конкретного ответа.
Родрирокр
1
Есть import * as Mix from "./A";и import A as Mix from "./A";то же самое?
Шафизаде
40

Дан Абрамов в ответе выше объясняет об экспорте по умолчанию и именном экспорте .

Какой использовать?

Цитата Дэвида Хермана : ECMAScript 6 поддерживает стиль экспорта «один / по умолчанию» и дает самый приятный синтаксис для импорта по умолчанию. Импорт именованных экспортов может и даже должен быть несколько менее кратким.

Однако в TypeScript именной экспорт предпочтителен из-за рефакторинга. Например, если вы экспортируете класс по умолчанию и переименовываете его, имя класса изменится только в этом файле, а не в других ссылках, а имя класса экспортированного имени будет переименовано во всех ссылках. Именованный экспорт также предпочтителен для коммунальных услуг.

В целом используйте все, что вы предпочитаете.

дополнительный

Экспорт по умолчанию на самом деле является именованным экспортом с именем по умолчанию, поэтому экспорт по умолчанию можно импортировать как:

import {default as Sample} from '../Sample.js';
Дипак Шарма
источник
2
AdditionalЛиния хорошая информация. import A from './A'не имеет смысла, если вы экспортируете без определения имени как export default 42.
PGT
8
Пожалуйста, постарайтесь не истолковать цитату Дэвида Германа. Это не означает , что « Это благоприятствовало всегда использовать одинарный экспорт / по умолчанию в ES6 », а « Поскольку одиночный экспорт настолько часто, ES6 поддерживает по умолчанию лучшим , и мы дали им сладкую синтаксис ».
Берги
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';
Brandon
источник
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');
theTypan
источник
Поскольку вы показываете сравнение с деструктуризацией, я бы добавил эквивалентное сравнение деструктуризации к вашему последнему комментарию: 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 Я бодибилдер
theTypan
1
Я думаю, что в любом объяснении импорта и когда использовать curlys против их использования, если вы не упоминаете разрушение объекта, вы действительно не даете лучшее объяснение. Когда я узнал о разрушении, я никогда не думал о том, почему я больше использую кудрявое, это просто интуитивно имело смысл
Эрик Бишард
6

Сводные ES6модули:

экспорт:

У вас есть 2 вида экспорта:

  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 на любую переменную, которую вы хотите

jadlmir
источник
4

Фигурные скобки ({}) используются для импорта именованных привязок, а концепция, лежащая в их основе, - это деструктурирующее назначение

Простую демонстрацию того, как оператор import работает с примером, можно найти в моем собственном ответе на аналогичный вопрос в разделе «Когда мы используем« {} »в импорте javascript?

samuelj90
источник
1
Вы определенно получите мой голос за лучший короткий ответ!
Эрик Бишард
0

Фигурные скобки используются только для импорта при названии экспорта. Если экспорт по умолчанию, то фигурные скобки не используются для импорта.

Абхишек Кумар
источник
0

Для экспорта по умолчанию мы не используем {} при импорте.

например

player.js

export default vx;

index.js

import vx from './player';

index.js введите описание изображения здесь

player.js введите описание изображения здесь

Если мы хотим импортировать все, что экспортируем, тогда мы используем * введите описание изображения здесь

user260778
источник