Verwenden von Klammern mit Javascript-Importsyntax

115

Ich bin auf eine Javascript-Bibliothek gestoßen, die die folgende Syntax zum Importieren von Bibliotheken verwendet:

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

Was ist der Unterschied zwischen der obigen Methode und der folgenden?

import React, Component, PropTypes from 'react';
Fuchs
quelle
4
Die Antwort ist in der Dokumentation
Adeneo
4
Die Mitglieder, die aus dem Modul importiert werden sollen, sind in geschweiften
Klammern
1
Ha. Wenn wir alle Male eliminieren würden, könnte man eine SO-Frage mit "RTFM" beantworten, könnte sogar Jon Skeet weniger als sechs Ziffern haben. ; ^)
Ruffin

Antworten:

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

Dies sagt:

Importieren Sie den Standard - Export aus 'react'unter dem Namen Reactund importieren Sie die Namen Exporte Componentund PropTypesunter den gleichen Namen.

Dies kombiniert die beiden gängigen Syntaxen, die Sie wahrscheinlich gesehen haben

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

Der erste dient zum Importieren und Benennen des Standardexports, der zweite zum Importieren der angegebenen benannten Exporte.

In der Regel stellen die meisten Module entweder einen einzelnen Standardexport oder eine Liste benannter Exporte bereit. Es ist etwas weniger üblich, dass ein Modul sowohl einen Standardexport als auch benannte Exporte bereitstellt . Wenn jedoch ein Feature am häufigsten importiert wird, aber auch zusätzliche Unter-Features, ist es ein gültiges Design, das erste als Standard und die übrigen als benannte Exporte zu exportieren. In solchen Fällen würden Sie die importSyntax verwenden, auf die Sie sich beziehen.

Die anderen Antworten liegen irgendwo zwischen falsch und verwirrend, möglicherweise weil die MDN-Dokumente zum Zeitpunkt der Beantwortung dieser Frage falsch und verwirrend waren. MDN zeigte das Beispiel

import name from "module-name";

und gesagt nameist der "Name des Objekts, das die importierten Werte erhält". Aber das ist irreführend und falsch; Erstens gibt es nur einen Importwert, der "empfangen" wird (warum nicht einfach "zugewiesen zu" oder "verwendet, um darauf zu verweisen" sagen) name, und der Importwert ist in diesem Fall der Standardexport aus dem Modul .

Eine andere Möglichkeit, dies zu erklären, besteht darin, zu beachten, dass der obige Import genau identisch mit ist

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

und das Beispiel des OP ist genau identisch mit

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

Die MDN-Dokumentation zeigte das Beispiel

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

und behauptete, dass es bedeutet

Importieren Sie den gesamten Inhalt eines Moduls, wobei einige auch explizit benannt werden. Dies fügt myModule(sic) foound barin den aktuellen Bereich ein. Beachten Sie, dass foound myModule.foodie gleichen sind wie barundmyModule.bar

Was MDN hier gesagt hat und welche anderen Antworten aufgrund der falschen MDN-Dokumentation behaupten, ist absolut falsch und basiert möglicherweise auf einer früheren Version der Spezifikation. Was dies tatsächlich tut, ist

Importieren Sie den Standardmodulexport und einige explizit benannte Exporte. Diese Einsätze MyModule, foound barin den aktuellen Bereich. Die Exportnamen foound barsind nicht zugänglich überMyModule , was der Standardexport ist , nicht irgendein Dach, das alle Exporte abdeckt.

(Der Standardmodulexport ist der mit der export defaultSyntax exportierte Wert , der auch sein kann export {foo as default}.)

Die Verfasser der MDN-Dokumentation sind möglicherweise mit dem folgenden Formular verwechselt worden:

import * as MyModule from 'my-module';

Dies importiert alle Exporte von my-moduleund macht sie unter Namen wie zugänglich MyModule.name. Auf den Standardexport kann auch zugegriffen werden MyModule.default, da der Standardexport eigentlich nichts anderes als ein anderer benannter Export mit dem Namen ist default. In dieser Syntax gibt es keine Möglichkeit, nur eine Teilmenge der benannten Exporte zu importieren, obwohl man den Standardexport importieren könnte, wenn es einen zusammen mit allen benannten Exporten mit gibt

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

quelle
1
Babel akzeptiert from '/path/to/my-module.js', obwohl ich persönlich benutze from '/path/to/my-module'.
Royhowie
5
Mit solch einer detaillierten Erklärung sollten Sie auch hinzufügen, wie sie exportiert werden, um so importiert zu werden.
Caio Iglesias
37
import React, { Component, PropTypes } from 'react'

Dadurch werden die ausgeführten greifen { Component, PropTypes }Mitglieder aus dem 'react'Modul und ordnen sie Componentund PropTypes, respectively. Reactentspricht dem defaultExport des Moduls .

Wie von Torazaburo unten bemerkt , ist dies dasselbe wie

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

Das ist eine Abkürzung für

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

Hier ist ein weiteres Beispiel ( Link zum Kern ):

// 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...'

Ich habe das zweite Beispiel mit babel getestet:

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

und bekam einen Syntaxfehler.

~/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 | 

Als Referenz können Sie die neue importDokumentation von MDN nachlesen . Es bedarf jedoch offenbar einer technischen Überprüfung. Der Blogbeitrag von Dr. Axel Rauschmayer ist vorerst eine bessere Referenz.

Royhowie
quelle
1
Dadurch werden die Eigenschaften {Component, PropTypes} aus den Exporten im Modul 'react' abgerufen und sie React zugewiesen. Das ist falsch. Es weist den Standardexport Reactund den benannten Exporten Componentsowie gleichnamigen PropTypesVariablen zu. Leider sind die MDN-Dokumente falsch, wie Sie herausfinden würden, wenn Sie es versuchen würden. Siehe 2ality.com/2014/09/es6-modules-final.html . Außerdem hat die Importsyntax absolut nichts mit der Destrukturierungszuweisung zu tun.
3
In Bezug auf Ihren Kommentar zum "neuen import Dokumentation", der den Revisionsverlauf dieses MDN-Artikels überprüft, wurden die von Ihnen zitierten Teile nicht überarbeitet, seit die Seite vor mehr als einem Jahr zum ersten Mal geschrieben wurde. In diesem Zeitraum war die Modulsyntax schnell ändern.
1
@torazaburo Ich habe meine Antwort umgeschrieben, um genauer zu sein.
Royhowie
@royhowie Vielen Dank für dieses Beispiel! Ich habe buchstäblich eine weitere Stunde gespart, um mich gedankenlos umzuschauen ... Ich habe nur eine Frage. In example3.jswarum es gedruckt wird undefinedfür console.log(d)? Seitdem haben export default { a, b, d }Sie es exportiert myModule.js.
CapturedTree
2
@ 1290 In myModule.js, beachten Sie, dass a, bund ceinzeln exportiert wurden. Dies bedeutet, dass eine andere Datei sie direkt mit importieren kann import { a } from 'myModule'. Auf der anderen Seite dist es nur über den Standardexport verfügbar, sodass ein anderes Modul auf zwei Arten darauf import thisObjectContainsDefault from 'myModule'zugreifen kann: und über thisObjectContainsDefault.dOR import { default as wrapperObject }und wrapperObject.d. Der Vorteil des zweiten Ansatzes besteht darin, dass Sie auch Elemente abrufen können, die einzeln exportiert wurden, wie in zu sehen ist example3.js.
Royhowie