`export const` vs.` export default` no ES6

204

Estou tentando determinar se há grandes diferenças entre esses dois, além de poder importar export defaultapenas fazendo:

import myItem from 'myItem';

E usando export consteu posso fazer:

import { myItem } from 'myItem';

Gostaria de saber se existem diferenças e / ou casos de uso além deste.

ajmajmajma
fonte
1
Usar constfará com que o identificador seja somente leitura. Portanto, no caso de valores primitivos, você pode considerar isso imutável. Observe que o valor em si não é imutável; portanto, objetos, matrizes etc. podem ser alterados - apenas não são reatribuídos.
Spmurrayzzz
4
@spmurrayzzz: FWIW, ligações de importação também são imutáveis, assim como const.
Felix Kling
obrigado pela @FelixKling esclarecimento, não sabia que
spmurrayzzz
@ FelixKling: De fora, pelo menos. Eles podem não ser constantes, mas as exportações podem ser alteradas.
Bergi 9/11/2015
@Bergi: direito, é por isso que eu disse ligações de importação ;)
Felix Kling

Respostas:

327

É uma exportação nomeada versus uma exportação padrão. export consté uma exportação nomeada que exporta uma declaração ou declarações const.

Para enfatizar: o que importa aqui é a exportpalavra - chave constusada para declarar uma declaração ou declarações const. exporttambém pode ser aplicado a outras declarações, como declarações de classe ou função.

Exportação padrão ( export default)

Você pode ter uma exportação padrão por arquivo. Ao importar, você deve especificar um nome e importar da seguinte maneira:

import MyDefaultExport from "./MyFileWithADefaultExport";

Você pode dar a esse nome qualquer nome que desejar.

Exportação nomeada ( export)

Com exportações nomeadas, você pode ter várias exportações nomeadas por arquivo. Importe as exportações específicas que você deseja colocar entre chaves:

// ex. importing multiple exports:
import { MyClass, MyOtherClass } from "./MyClass";
// ex. giving a named import a different name by using "as":
import { MyClass2 as MyClass2Alias } from "./MyClass2";

// use MyClass, MyOtherClass, and MyClass2Alias here

Ou é possível usar um padrão junto com importações nomeadas na mesma instrução:

import MyDefaultExport, { MyClass, MyOtherClass} from "./MyClass";

Importação de namespace

Também é possível importar tudo do arquivo em um objeto:

import * as MyClasses from "./MyClass";
// use MyClasses.MyClass, MyClasses.MyOtherClass and MyClasses.default here

Notas

  • A sintaxe favorece as exportações padrão como um pouco mais concisas porque seu caso de uso é mais comum ( consulte a discussão aqui ).
  • Uma exportação padrão é na verdade uma exportação nomeada com o nome defaultpara que você possa importá-la com uma importação nomeada:

    import { default as MyDefaultExport } from "./MyFileWithADefaultExport";
David Sherret
fonte
24

export default afeta a sintaxe ao importar a "coisa" exportada, ao permitir importar, o que foi exportado, escolhendo o nome no import si, independentemente do nome em que foi exportado, simplesmente porque está marcado como "padrão".

Um caso de uso útil, que eu gosto (e uso), está permitindo exportar uma função anônima sem precisar explicitamente nomeá-la, e somente quando essa função é importada, deve ser dado um nome:


Exemplo:

Exportar 2 funções, uma é default:

export function divide( x ){
    return x / 2;
}

// only one 'default' function may be exported and the rest (above) must be named
export default function( x ){  // <---- declared as a default function
    return x * x;
}

Importe as funções acima. Criando um nome para defaultesse:

// The default function should be the first to import (and named whatever)
import square, {divide} from './module_1.js'; // I named the default "square" 

console.log( square(2), divide(2) ); // 4, 1

Quando a {}sintaxe é usada para importar uma função (ou variável), isso significa que tudo o que é importado foi nomeado quando exportados, por isso é preciso importá-lo pelo exato mesmo nome, ou então a importação não iria funcionar.


Exemplos errôneos:

  1. A função padrão deve ser a primeira a importar

    import {divide}, square from './module_1.js
  2. divide_1não foi exportado module_1.js, portanto nada será importado

    import {divide_1} from './module_1.js
  3. squarenão foi exportado module_1.js, porque {}diz ao mecanismo para procurar explicitamente apenas exportações nomeadas .

    import {square} from './module_1.js
vsync
fonte
Isso não significa que exporta uma única coisa. Você pode ter vários nomeados e um padrão no mesmo módulo. Padrão simplesmente significa exatamente isso - é a exportação padrão se você não especificar o nome ao importar, ou seja, em import something fromvez de import { somethingNamed } from.
Andris
Eu também aprendi nova palavra Inglês aqui: "errada" +1 para isso
Yuval Levy
12

Nota secundária: considere que quando você importa de uma exportação padrão, a nomeação é completamente independente. Isso realmente afeta as refatorações.

Digamos que você tenha uma classe Foocomo esta com uma importação correspondente:

export default class Foo { }

//the name 'Foo' could be anything, since it's just an
//identifier for the default export
import Foo from './Foo'

Agora, se você refatorar sua Fooclasse Bare também renomear o arquivo, a maioria dos IDEs NÃO afetará sua importação. Então você vai acabar com isso:

export default class Bar { }

//the name 'Foo' could be anything, since it's just an
//identifier for the default export.
import Foo from './Bar'

Especialmente no Typescript, eu realmente aprecio as exportações nomeadas e a refatoração mais confiável. A diferença é apenas a falta da defaultpalavra - chave e das chaves. Essa btw também impede que você digite erros de digitação na importação, pois você tem a verificação de tipo agora.

export class Foo { }

//'Foo' needs to be the class name. The import will be refactored
//in case of a rename!
import { Foo } from './Foo'
Philipp Sumi
fonte
2
" 'Foo' precisa ser o nome da classe. " - não! Você pode fazer tão facilmente import { Foo as Anything } from …quanto import Anything from …nas exportações padrão.
Bergi
O fato de você poder renomeá-lo com um asnão é realmente o ponto desse comentário de origem. Obrigado pelo voto negativo; p
Philipp Sumi
1
Não diminuí o voto, mas não tenho certeza se esse argumento é convincente. Não sei se quero que meu IDE renomeie todas as importações ao refatorar um único módulo. É exatamente disso que se trata a modularização :-) E parece ser mais um "problema" do IDE, não um motivo para escolher o estilo de exportação ...
Bergi
Concordo que usei exportações nomeadas para o desenvolvedor UX aqui - mas, você poderia argumentar que o Typescript em si é tudo sobre isso. Refatoro com frequência e, como normalmente tenho uma classe (no meu caso: React Component) por arquivo, desejo absolutamente que as importações sigam um componente renomeado para não criar uma desconexão. Obviamente, isso pode ou não fazer sentido, dependendo do desenvolvedor individual.
Philipp Sumi
Encontrei um artigo que diz a mesma coisa. Talvez uma posição razoável possa ser: devemos usar export defaultpara exportar o objeto principal de um projeto, em particular de um pacote npm (ele substitui a module.exports =). Porém, internamente em um projeto, é melhor usar apenas exportações nomeadas.
Paleo
7

A partir da documentação :

Exportações nomeadas são úteis para exportar vários valores. Durante a importação, será possível usar o mesmo nome para se referir ao valor correspondente.

Em relação à exportação padrão, há apenas uma única exportação padrão por módulo. Uma exportação padrão pode ser uma função, uma classe, um objeto ou qualquer outra coisa. Este valor deve ser considerado como o valor exportado "principal", pois será o mais simples de importar.

James Sumners
fonte
0

Quando você coloca o padrão, é chamado de exportação padrão. Você pode ter apenas uma exportação padrão por arquivo e pode importá-lo para outro arquivo com o nome que desejar. Quando você não coloca o padrão, chamado export export, você deve importá-lo para outro arquivo usando o mesmo nome com chaves dentro dele.

Abdullah Danyal
fonte
0

Eu tive o problema de o navegador não usar es6.

Eu corrigi-lo com:

 <script type="module" src="index.js"></script>

O módulo type informa ao navegador para usar o ES6.

export const bla = [1,2,3];

import {bla} from './example.js';

Então deve funcionar.

Marcel Zebrowski
fonte