Почему результаты различаются в зависимости от расположения фигурных скобок?

119

Почему приведенные ниже фрагменты кода, взятые из этой статьи , дают разные результаты из-за всего лишь одного изменения в расположении фигурных скобок?

Когда открывающая фигурная скобка {находится на новой строке, test()возвращается undefined, и в предупреждении отображается «нет - она ​​сломалась: undefined».

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

Когда фигурная скобка находится на той же строке, что и return, test()возвращает объект, и предупреждается "фантастический".

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
источник
семантика полу-вставки после returnнемного отличается от в других местах, и разрыв строки «означает больше» в этом месте, чем «в середине».
dandavis 03

Ответы:

165

Это одна из ловушек JavaScript: автоматическая вставка точки с запятой. Строки, которые не заканчиваются точкой с запятой, но могут быть концом оператора, автоматически завершаются, поэтому ваш первый пример выглядит примерно так:

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

См. Также руководство по стилю JS Дугласа Крокфорда , в котором упоминается вставка точки с запятой.

Во втором примере вы возвращаете объект (построенный фигурными скобками) со свойством javascriptи его значением "fantastic", фактически таким же, как этот:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}
отстой
источник
5
Интересный факт: на некоторых движках вы можете закомментировать автоматически вставляемые точки с запятой
Кристофер Тарквини,
1
@ChrisT: Что? Какие? Это где-нибудь исследуется?
Шон Макмиллан
1
@SeanMcMillan Я определенно читал статьи об этом, но не могу найти ни одной из них с помощью быстрого поиска. Я помню, что установка return /*и затем */{ эффективно закомментировала скрытую точку с запятой в старых версиях Chrome. Не уверен, что это все еще применимо
Кристофер Тарквини
2
Из-за этих причуд 10 лет назад я дал себе обещание: держаться подальше от Интернета! Я молился, чтобы Interwebs исчезли ... К сожалению, все пошло не так, как планировалось, и теперь мне приходится бороться и с этими проблемами. Karma ab * tch :)
Jowen
1
Я видел людей, которые категорически против точек с запятой в JavaScript, мне всегда было интересно, что они делают с тем дополнительным временем, которое они экономят, не ставя точки с запятой.
Иман Мохамади
9

Javascript не требует точек с запятой в конце операторов, но недостатком является то, что он должен угадывать, где находятся точки с запятой. В большинстве случаев это не проблема, но иногда возникает точка с запятой там, где вы ее не намеревались.

Пример из моего сообщения в блоге об этом ( Javascript - почти не линейный ):

Если вы отформатируете код так:

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

Тогда это интерпретируется так:

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

Оператор return принимает форму без параметров, а аргумент становится самостоятельным утверждением.

То же самое происходит с вашим кодом. Функция интерпретируется как:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}
Guffa
источник
3

Я лично предпочитаю стиль Allman для удобочитаемости (а не стиль K&R).

Вместо того…

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

Мне нравиться…

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

  return obj;
}

Но это обходной путь. Хотя я могу жить с этим.

Майкл Р
источник
3
Я считаю, что нам следует избегать личных предпочтений, отклоняющихся от общепринятых. Мы должны следовать выбору большинства, что способствует единообразию, что повысит читаемость,
Джоуэн
1
Я считаю его код более читабельным, чем K&R. Довольно субъективно, когда вы имеете в виду «читабельный»
Бран
Я тоже предпочитаю Allman ... но из-за ASI, когда мне нужно вернуть объект, я оставляю полу в той же строке, что и return. Я предпочитаю это, чем добавлять одну строку «var x =» ...
Мик
1

Это потому, что javascript чаще всего ставит ";" в конце каждой строки, поэтому обычно, когда вы возвращаете {в той же строке, движок javascript видит, что будет что-то еще, и когда он в новой строке, он думает, что вы забыли поставить ";", и помещает его для вас.

Cichy
источник
1
Я не понимаю, почему ответы Цичи, Дарина и Иво были отклонены?
BoltClock
1

Фигурные скобки здесь указывают на создание нового объекта. Таким образом, ваш код эквивалентен:

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

который работает, тогда как если вы напишете:

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

это больше не работает.

Дарин Димитров
источник
0

Проблема действительно заключается в введении точки с запятой, как описано выше. Я только что прочитал хорошую запись в блоге на эту тему. В нем объясняется эта проблема и многое другое о javascript. Он также содержит несколько хороших ссылок. Вы можете прочитать это здесь

Иво ван дер Вейк
источник
Да, я тоже читал это, после прочтения я прошу здесь объяснить лучше от вдохновителя js.
JustLearn