Por que os resultados variam com base no posicionamento das chaves?

119

Por que os snippets de código abaixo, retirados de deste artigo , produzem resultados diferentes devido a apenas uma única alteração no posicionamento das chaves?

Quando a chave de abertura {está em uma nova linha, test()retorna undefinede "não - quebrou: indefinido" é exibido no alerta.

function test()
{
  return
  { /* <--- curly brace on new line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

Quando a chave está na mesma linha que return, test()retorna um objeto e "fantástico" é alertado.

function test()
{
  return { /* <---- curly brace on same line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

JustLearn
fonte
a semântica de semi-inserção posterior returné ligeiramente diferente do que em outros lugares, e uma quebra de linha "significa mais" naquele ponto do que "midstream".
dandavis

Respostas:

165

Essa é uma das armadilhas do JavaScript: inserção automática de ponto-e-vírgula. As linhas que não terminam com um ponto-e-vírgula, mas podem ser o final de uma instrução, são encerradas automaticamente, então seu primeiro exemplo se parece efetivamente com este:

function test()
{
  return; // <- notice the inserted semicolon
  { 
    javascript: "fantastic"
  };
}

Consulte também o guia de estilo JS de Douglas Crockford , que menciona a inserção de ponto e vírgula.

Em seu segundo exemplo, você retorna um objeto (construído pelas chaves) com a propriedade javascripte seu valor de "fantastic", efetivamente o mesmo que este:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}
Resíduo
fonte
5
Curiosidade: em alguns engines, você pode comentar os pontos-e-vírgulas inseridos automaticamente
Christopher Tarquini
1
@ChrisT: O quê? Quais? Isso é explorado em algum lugar?
Sean McMillan
1
@SeanMcMillan Eu definitivamente li artigos sobre isso, mas não consigo encontrar nenhum deles em uma pesquisa rápida. Lembro-me de que colocar return /*e */{ comentar efetivamente o ponto-e-vírgula oculto nas versões mais antigas do Chrome. Não tenho certeza se isso ainda se aplica
Christopher Tarquini
2
Por causa dessas peculiaridades, fiz uma promessa a mim mesma há 10 anos: fique longe da web! Rezei para que o Interwebs desaparecesse ... Infelizmente, não saiu como planejado, e agora tenho que lutar com esses problemas também. Karma é ab * tch :)
Jowen,
1
Já vi pessoas que são religiosamente contra o ponto-e-vírgula em JavaScript, sempre me perguntei o que eles fazem com esse tempo extra que economizam ao não colocar ponto-e-vírgula.
Iman Mohamadi
9

Javascript não requer ponto-e-vírgula no final das instruções, mas a desvantagem é que ele precisa adivinhar onde estão os pontos-e-vírgulas. Na maioria das vezes isso não é um problema, mas às vezes inventa um ponto-e-vírgula onde você não pretendia.

Um exemplo da postagem do meu blog sobre isso ( Javascript - quase não baseado em linhas ):

Se você formatar o código assim:

function getAnswer() {
   var answer = 42;
   return
      answer;
}

Então, é interpretado assim:

function getAnswer() {
  var answer = 42;
  return;
  answer;
}

A instrução de retorno assume sua forma sem parâmetros e o argumento se torna uma instrução própria.

O mesmo acontece com o seu código. A função é interpretada como:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}
Guffa
fonte
3

Eu pessoalmente prefiro o estilo Allman para facilitar a leitura (em vez do estilo K&R).

Ao invés de…

function test() {
  return {
    javascript : "fantastic"
  };
}

Eu gosto…

function test() 
{
  var obj =
  {
    javascript : "fantastic"
  };

  return obj;
}

Mas esta é uma solução alternativa. Eu posso viver com isso.

Michael R
fonte
3
Acho que devemos evitar preferências pessoais que se desviem do mainstream. Devemos seguir as escolhas da maioria, o que promove consistência, o que aumentará a legibilidade
Jowen
1
Acho seu código mais legível do que o K&R. Muito subjetivo quando você quer dizer "legível"
Bran
Prefiro o Allman também ... mas devido ao ASI, quando preciso devolver um objeto, deixo o semi na mesma linha do retorno. Eu prefiro isso do que adicionar uma linha "var x =" ...
Mik de
1

É porque o javascript geralmente coloca ";" no final de cada linha, então basicamente quando tiver return {in same line, javascript engine vê que haverá algo mais, e quando estiver em nova linha ele pensa que esqueceu de colocar ";", e coloca para você.

cichy
fonte
1
Não entendo por que as respostas de cichy, Darin e Ivo foram rejeitadas.
BoltClock
1

As chaves aqui indicam a construção de um novo objeto. Portanto, seu código é equivalente a:

function test() {
  var a = { javascript : "fantastic" };
  return a;
}

que funciona, enquanto se você escrever:

function test() {
  var a = { javascript : "fantastic" };
  return; // ; is automatically inserted 
      a;
}

não funciona mais.

Darin Dimitrov
fonte
0

O problema é na verdade a injeção de ponto-e-vírgula, conforme descrito acima. Acabei de ler uma boa postagem no blog sobre esse assunto. Ele explica esse problema e muito mais sobre javascript. Ele também contém algumas boas referências. Você pode ler aqui

Ivo van der Wijk
fonte
Sim, também li isso, depois de ler, peço aqui para explicar melhor pelo idealizador de js.
JustLearn