usando corchetes con sintaxis de importación javascript

115

Me encontré con una biblioteca de JavaScript que usa la siguiente sintaxis para importar bibliotecas:

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

¿Cuál es la diferencia entre el método anterior y el siguiente?

import React, Component, PropTypes from 'react';
zorro
fuente
4
La respuesta está en la documentación
adeneo
4
Los miembros que se van a importar desde el módulo están entre llaves
adeneo
1
Decir ah. Si elimináramos todas las veces que podría decirse que uno podría responder una pregunta SO con "RTFM", incluso Jon Skeet podría tener menos de seis cifras. ; ^)
ruffin

Respuestas:

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

Esto dice:

Importe la exportación predeterminada'react' con el nombre Reacte importe las exportaciones con nombreComponent y PropTypescon los mismos nombres.

Esto combina las dos sintaxis comunes que probablemente hayas visto

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

El primero se utiliza para importar y nombrar la exportación predeterminada, el segundo para importar las exportaciones con nombre especificadas.

Como regla general, la mayoría de los módulos proporcionarán una única exportación predeterminada o una lista de exportaciones con nombre. Es algo menos habitual para un módulo para proporcionar tanto una exportación por defecto y las exportaciones con nombre. Sin embargo, en el caso de que haya una característica que se importe con mayor frecuencia, pero también subcaracterísticas adicionales, es un diseño válido exportar la primera como predeterminada y las restantes como exportaciones con nombre. En tales casos, utilizaría la importsintaxis a la que se refiere.

Las otras respuestas están en algún lugar entre incorrectas y confusas, posiblemente porque los documentos de MDN en el momento en que se hizo esta pregunta eran incorrectos y confusos. MDN mostró el ejemplo

import name from "module-name";

y dicho namees el "nombre del objeto que recibirá los valores importados". Pero eso es engañoso e incorrecto; En primer lugar, solo hay un valor de importación, que será "recibido" (por qué no decir simplemente "asignado a" o "utilizado para referirse a") name, y el valor de importación en este caso es la exportación predeterminada del módulo. .

Otra forma de explicar esto es observar que la importación anterior es exactamente idéntica a

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

y el ejemplo del OP es precisamente idéntico a

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

La documentación de MDN pasó a mostrar el ejemplo

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

y afirmó que significa

Importe el contenido de un módulo completo, y algunos también se nombrarán explícitamente. Esto inserta myModule(sic) foo, y baren el alcance actual. Tenga en cuenta que fooy myModule.fooson lo mismo, como son barymyModule.bar

Lo que MDN dijo aquí, y lo que afirman otras respuestas basadas en la documentación de MDN incorrecta, es absolutamente incorrecto y puede basarse en una versión anterior de la especificación. Lo que esto realmente hace es

Importe la exportación del módulo predeterminado y algunas exportaciones con nombres explícitos. Esto inserta MyModule, fooy baren el ámbito actual. No se puede acceder a los nombres de exportación fooy a través debarMyModule , que es la exportación predeterminada , no un paraguas que cubra todas las exportaciones.

(La exportación del módulo predeterminado es el valor exportado con la export defaultsintaxis, que también podría ser export {foo as default}).

Los escritores de documentación de MDN pueden haberse confundido con el siguiente formulario:

import * as MyModule from 'my-module';

Esto importa todas las exportaciones de my-moduley las hace accesibles con nombres como MyModule.name. La exportación predeterminada también es accesible como MyModule.default, ya que la exportación predeterminada no es más que otra exportación nombrada con el nombre default. En esta sintaxis, no hay forma de importar solo un subconjunto de las exportaciones con nombre, aunque se podría importar la exportación predeterminada, si existe, junto con todas las exportaciones con nombre, con

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

fuente
1
Babel acepta from '/path/to/my-module.js', aunque yo personalmente uso from '/path/to/my-module'.
Royhowie
5
Con una explicación tan detallada, también debe agregar cómo se exportan para ser importados así.
Caio Iglesias
37
import React, { Component, PropTypes } from 'react'

Esto tomará los { Component, PropTypes }miembros exportados del 'react'módulo y los asignará a Componenty PropTypes, respectivamente. Reactserá igual a la defaultexportación del módulo .

Como señala torazaburo a continuación , esto es lo mismo que

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

que es la abreviatura de

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

Aquí hay otro ejemplo ( enlace a la esencia ):

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

Probé el segundo ejemplo con babel:

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

y obtuve un error de sintaxis.

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

Como referencia, puede leer la nueva importdocumentación de MDN. Sin embargo, aparentemente necesita una revisión técnica. La publicación del blog del Dr. Axel Rauschmayer es una mejor referencia por ahora.

Royhowie
fuente
1
Esto tomará las propiedades de {Component, PropTypes} de las exportaciones en el módulo 'react' y las asignará a React. Esto es incorrecto. Asigna la exportación predeterminada a las exportaciones con Reactnombre Componenty las PropTypesvariables del mismo nombre. Desafortunadamente, los documentos de MDN están equivocados, como descubriría si lo intentara. Consulte 2ality.com/2014/09/es6-modules-final.html . Además, la sintaxis de importación no tiene absolutamente nada que ver con la asignación de desestructuración.
3
Con respecto a su comentario sobre la "nueva importdocumentación", al revisar el historial de revisión de ese artículo de MDN, las partes que está citando no se han revisado desde que la página se escribió por primera vez hace más de un año, un período durante el cual la sintaxis del módulo fue cambiando rápidamente
1
@torazaburo Reescribí mi respuesta para ser más precisa.
Royhowie
@royhowie ¡¡Muchas gracias por este ejemplo !! Literalmente me ahorré otra hora de navegar sin pensar ... Solo tengo una pregunta. En example3.js¿Por qué se imprimirá undefinedpara console.log(d)? Como lo hizo, export default { a, b, d }lo exportó en formato myModule.js.
CapturedTree
2
@ 1290 En myModule.jsnota de que a, by cfueron exportados de forma individual. Esto significa que otro archivo puede importarlos directamente con import { a } from 'myModule'. Por otro lado, dsolo está disponible a través de la exportación predeterminada, por lo que otro módulo puede acceder a él de dos maneras: import thisObjectContainsDefault from 'myModule'y acceder a través de thisObjectContainsDefault.dOR import { default as wrapperObject }y wrapperObject.d. El beneficio del segundo enfoque es que también puede obtener elementos que se exportaron individualmente, como se puede ver en example3.js.
Royhowie