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);
}


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;
}

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"
  };
}

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.


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ê.


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.


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


Sim, também li isso, depois de ler, peço aqui para explicar melhor pelo idealizador de js.
— JustLearn
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.