desestruturação de objetos sem var


97

Por que a desestruturação de objetos gera um erro se não há uma varpalavra-chave antes dela?

{a, b} = {a: 1, b: 2};

lança SyntaxError: expected expression, got '='

Os três exemplos a seguir funcionam sem problemas

var {a, b} = {a: 1, b: 2};
var [c, d] = [1, 2];
    [e, f] = [1, 2];

Pergunta bônus: por que não precisamos de uma varpara a desestruturação do array?

Eu encontrei o problema fazendo algo como

function () {
  var {a, b} = objectReturningFunction();

  // Now a and b are local variables in the function, right?
  // So why can't I assign values to them?

  {a, b} = objectReturningFunction();
}

Respostas:


158

O problema decorre do fato de os {...}operadores terem vários significados em JavaScript.

Quando {aparece no início de uma Declaração , sempre representará um bloco , ao qual não pode ser atribuído. Se aparecer posteriormente na Declaração como uma Expressão , representará um Objeto.

O varajuda a fazer essa distinção, já que não pode ser seguido por uma declaração , como o agrupamento parênteses :

( {a, b} = objectReturningFunction() );

De seus documentos: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration

Notas: Os parênteses (...) em torno da instrução de atribuição são necessários ao usar a atribuição de desestruturação literal de objeto sem uma declaração.

{a, b} = {a: 1, b: 2} não é uma sintaxe autônoma válida, pois o {a, b} no lado esquerdo é considerado um bloco e não um literal de objeto.

No entanto, ({a, b} = {a: 1, b: 2}) é válido, assim como var {a, b} = {a: 1, b: 2}

Sua (...) expressão deve ser precedida por um ponto e vírgula ou pode ser usada para executar uma função na linha anterior.


Se aparecer posteriormente na Declaração como uma Expressão, representará um Objeto. Isso significa que nunca podemos ter o escopo do bloco entre parênteses de agrupamento
sharad_kalya

A dica de agrupamento entre parênteses é ótima.
James Smith

Este é um conhecimento brilhantemente obscuro que me deixou perplexo. Ele permite a desestruturação em todo o escopo (bem, mais ou menos - você ainda precisa declarar suas variáveis, é claro). Mas ele resolve uma restrição de usar cadeias de promessas ao mesmo tempo em que precisa usar várias variáveis ​​resolvidas de uma etapa de uma cadeia de promessas em outra, sem criar muita confusão. Obrigado.
Kevin Teljeur

22

Se você escrever Javascript sem ponto- e- vírgula , a sintaxe de 'atribuição sem declaração' deve ser precedida por um ponto-e-vírgula para funcionar de maneira previsível

let a, b

;({a, b} = objectReturningFunction()) // <-- note the preceding ;

Só queria destacar isso porque me pegou, e espero que possa poupar algum tempo para outros descobrirem por que não funciona e / ou produz resultados estranhos com formatadores de código como prettier.

Na verdade, está bem ali na resposta aceita (última linha dos documentos citados), mas fácil de perder, especialmente sem ver um exemplo!


1
Sim. Uma razão para as pessoas usarem ponto e vírgula!
jfriend00,

0

Aqui está outra maneira:

let {} = {a, b} = objectReturningFunction()

Prós:

  • Sem parênteses necessário
  • Sem ponto e vírgula necessário
  • A atribuição extra é um ambiente autônomo garantido (visto que nenhuma coisa estranha está acontecendo)

Contras:

  • Parece um pouco estranho, embora na minha opinião não seja mais estranho que o !(){...}() IIFE .
  • Pode ser confuso por que está lá. É garantido que irá confundir as pessoas no primeiro encontro, então eu não aconselho usá-lo como algo isolado.

Tipo de sente como de Iife são mais comparável ao ;({ a, b })que let {} = { ... }. Bom truque. :)
shuckster

@ proto-n, +1, ideia muito inteligente. Como você descobriu isso?
Pacerier
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.