использование скобок с синтаксисом импорта javascript

116

Я наткнулся на библиотеку javascript, которая использует следующий синтаксис для импорта библиотек:

import React, { Component, PropTypes } from 'react';

В чем разница между вышеуказанным методом и следующим?

import React, Component, PropTypes from 'react';
лиса
источник
4
Ответ находится в документации
adeneo
4
Члены, которые нужно импортировать из модуля, заключены в фигурные скобки
adeneo
1
Ха. Если бы мы исключили все случаи, когда можно было бы ответить на SO-вопрос с помощью «RTFM», даже Джон Скит мог бы иметь менее шестизначные цифры. ; ^)
ruffin

Ответы:

174
import React, { Component, PropTypes } from 'react';

Это говорит:

Импорт по умолчанию экспорта из 'react'под именем Reactи импортировать именованные экспорта Componentи PropTypesпод теми же названиями.

Это объединяет два общих синтаксиса, которые вы, вероятно, видели

import React from 'react';
import { Component, PropTypes } from 'react';

Первый используется для импорта и наименования экспорта по умолчанию, второй - для импорта указанного именованного экспорта.

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

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

import name from "module-name";

и сказано name- это «имя объекта, который получит импортированные значения». Но это заблуждение и неверно; во-первых, есть только одно значение импорта, которое будет «получено» (почему бы просто не сказать «назначено» или «используется для ссылки») name, а значение импорта в этом случае является экспортом по умолчанию из модуля .

Другой способ объяснить это - отметить, что приведенный выше импорт в точности идентичен

import { default as name } from "module-name";

и пример OP в точности идентичен

import { default as React, Component, PropTypes } from 'react';

В документации MDN был показан пример.

import MyModule, {foo, bar} from "my-module.js";

и утверждал, что это означает

Импортируйте содержимое всего модуля, некоторые из которых также имеют явные имена. Это вставляет myModule(sic) foo, и barв текущую область видимости. Обратите внимание, что fooи myModule.fooтакие же, как barиmyModule.bar

То, что здесь сказал MDN, и то, что другие ответы утверждают, основанные на неверной документации MDN, абсолютно неверно и может быть основано на более ранней версии спецификации. На самом деле это

Импортируйте экспорт модуля по умолчанию и некоторые явно названные экспорты. Это вставляет MyModule, fooи barв текущую область. Имена экспорта fooи barявляются не доступны черезMyModule , который является по умолчанию экспорта, а не какой - то зонтик охватывает весь экспорт.

(Экспорт модуля по умолчанию - это значение, экспортированное с export defaultсинтаксисом, который также может быть export {foo as default}.)

Авторы документации MDN могли запутаться в следующей форме:

import * as MyModule from 'my-module';

Это импортирует весь экспорт из файлов my-moduleи делает их доступными под такими именами, как MyModule.name. Экспорт по умолчанию также доступен как MyModule.default, поскольку экспорт по умолчанию на самом деле не что иное, как другой именованный экспорт с именем default. В этом синтаксисе нет способа импортировать только подмножество именованных экспортов, хотя можно импортировать экспорт по умолчанию, если он есть, вместе со всеми именованными экспортами, с

import myModuleDefault, * as myModule from 'my-module';

источник
1
Babel принимает from '/path/to/my-module.js', хотя лично пользуюсь from '/path/to/my-module'.
royhowie
5
С таким подробным объяснением вы также должны добавить, как они экспортируются, чтобы их можно было импортировать таким образом.
Кайо Иглесиас
37
import React, { Component, PropTypes } from 'react'

Это будет захватывать экспортируемые { Component, PropTypes }элементы из 'react'модуля и присвоить их Componentи PropTypes, соответственно. Reactбудет равно defaultэкспорту модуля .

Как отмечает торазабуро ниже , это то же самое, что

import { default as React, Component, PropTypes } from 'react'

что является сокращением для

import { default as React, Component as Component, PropTypes as PropTypes} from 'react'

Вот еще один пример ( ссылка на суть ):

// myModule.js
export let a = true
export let b = 42
export let c = 'hello, world!'
// `d` is not exported alone
let d = 'some property only available from default'

// this uses the new object literal notation in es6
// {myVar} expands to { myVar : myVar }, provided myVar exists
// e.g., let test = 22; let o = {test}; `o` is then equal to { test : 22 }
export default { a, b, d }

// example1.js
import something from 'myModule'
console.log(something)
// this yields (note how `c` is not here):
/*
  {
    a : true,
    b : 42,
    d : 'some property only available from default'
  }
*/

// example2.js
import something, { c } from 'myModule'
console.log(something)  // same as above; the `default` export
console.log(c)          // c === 'hello, world!'

// example3.js
import { a, b, d, default as something } from 'myModule'
console.log(a)            // a === true
console.log(b)            // b === 42
console.log(d)            // d === undefined (we didn't export it individually)
console.log(something.d)  // something.d === 'some property...'

Второй пример я проверил с помощью babel:

import test, test3, test2 from './app/lib/queries.js'
console.log(test, test3, test2)

и получил синтаксическую ошибку.

~/code/repo/tutoring $ babel-node test.js
/Users/royhowie/.node/lib/node_modules/babel/node_modules/babel-core/lib/babel/transformation/file/index.js:601
      throw err;
            ^
SyntaxError: /Users/royhowie/code/repo/tutoring/test.js: Unexpected token (1:13)
> 1 | import test, test3, test2 from './app/lib/queries.js'
    |              ^
  2 | 
  3 | console.log(test, test3, test2)
  4 | 

Для справки вы можете прочитать новую importдокументацию от MDN. Однако очевидно, что он нуждается в техническом рассмотрении. Сообщение в блоге доктора Акселя Раушмайера - лучшая ссылка на данный момент.

royhowie
источник
1
Это захватит свойства {Component, PropTypes} из экспорта в модуле 'react' и назначит их React. Это неверно. Он назначает экспорт по умолчанию React, а также именованные экспорт Componentи PropTypesпеременные с тем же именем. К сожалению, документы MDN ошибочны, как вы могли бы понять, если бы попробовали. См. 2ality.com/2014/09/es6-modules-final.html . Кроме того, синтаксис импорта не имеет ничего общего с деструктурирующим назначением.
3
Что касается вашего комментария о «новой importдокументации», в котором рассматривается история изменений этой статьи MDN, части, которые вы цитируете, не редактировались с тех пор, как страница была впервые написана более года назад, то есть периода, в течение которого синтаксис модуля был быстро меняется
1
@torazaburo Я переписал свой ответ, чтобы быть точнее.
royhowie
@royhowie Большое спасибо за этот пример !! Буквально сэкономил еще один час бездумного просмотра ... У меня только один вопрос. В example3.jsпочему это напечатать undefinedдля console.log(d)? Поскольку вы это сделали, export default { a, b, d }вы экспортировали его в формате myModule.js.
CapturedTree
2
@ 1290 In myModule.js, отметим , что a, bи cбыли вывезены в индивидуальном порядке . Это означает, что другой файл может импортировать их напрямую с помощью import { a } from 'myModule'. С другой стороны, dон доступен только через экспорт по умолчанию, поэтому другой модуль может получить к нему доступ двумя способами: import thisObjectContainsDefault from 'myModule'и получить к нему доступ через thisObjectContainsDefault.dИЛИ import { default as wrapperObject }и wrapperObject.d. Преимущество второго подхода заключается в том, что вы также можете захватывать элементы, которые были экспортированы индивидуально, как это видно на example3.js.
royhowie