Опасные последствия стиля Allman в JavaScript

Я не могу вспомнить, где, но недавно я передал комментарий, в котором пользователь сказал, что 1TBS является более предпочтительным, чем Allman в JavaScript, и сказал, что Allman имеет опасные последствия для JavaScript.

Это было правильное утверждение? Если так, то почему?

5 ответов

Решение

return не могу иметь LineTerminator после этого так:

return
{


};

рассматривается как return; (вернуть undefined) вместо return {}; (вернуть объект)

Смотрите правила для Automatic Semicolon Insertion (ASI) для большего.

Это правильное утверждение.

Потому что у движков JavaScript есть то, что называется ASI (автоматическая вставка точки с запятой), которая вставляет точку с запятой в случае необходимости в возвращаемые строки. "При необходимости" неоднозначно; иногда это работает, а иногда нет. Смотрите правила.

Итак, как сказано в других ответах:

return
{
};

// Is read by the JavaScript engine, after ASI, as:
return; // returns undefined
{ // so this is not even executed
};

Так что это не рекомендуется для return заявления.

Однако, если ваши рекомендации рекомендуют стиль Allman для объявлений функций, это прекрасно. Я знаю некоторых, которые делают.

return {
    a: "A",
    b: "B"
};

// vs.

return // Semicolon automatically inserted here! Uh oh!
{
    a: "A",
    b: "B"
}

Я думаю, что это зависит от заявления. Например, оператор возврата может быть нарушен, если открывающая скобка находится на новой строке. Больше информации здесь.

Вы можете использовать стиль Allman или Allman-8, если вы помните один особый случай с ключевыми словами и .

Отделение литералов объектов от ключевых слов или перевода строки не работает в JavaScript из-за правил ASI, которые имеют специальное исключение для операторов и:

  1. Когда при анализе программы слева направо встречается токен, который разрешен некоторым производством грамматики, но производство является ограниченным производством, и токен будет первым токеном для терминала или нетерминала сразу после аннотации. « [здесь нет LineTerminator] » внутри ограниченного производства (поэтому такой токен называется ограниченным токеном ), и ограниченный токен отделяется от предыдущего токена хотя бы одним LineTerminator, то перед ограниченным токеном автоматически вставляется точка с запятой .

а также

ПРИМЕЧАНИЕ . Ниже приведены единственные ограниченные постановки в грамматике:
[...]
ReturnStatement :
[здесь нет LineTerminator] Expression ;
ThrowStatement :
[здесь нет LineTerminator] Expression ;

(Есть и другие ограниченные производства, но они не поддерживают фигурные скобки, поэтому они не важны для стиля Оллмана.)

На практике это не работает так, как вы ожидаете :

      return
{
        status: "successful",
        user:
        {
               id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
               label: "John Doe",
        },
};

потому что это будет интерпретироваться как (обратите внимание на точку с запятой после возврата!)

      return;
{
        status: "successful",
        user:
        {
               id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
               label: "John Doe",
        },
};

Итак, вы должны либо использовать синтаксис

      const response =
{
        status: "successful",
        user:
        {
               id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
               label: "John Doe",
        },
};
return response;

или же

      return {
        status: "successful",
        user:
        {
               id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
               label: "John Doe",
        },
};

вместо.

Я лично считаю, что имена возвращаемых структур в любом случае более читабельны, поэтому я использую это. Я также везде использую Allman-8, что практически означает, что вы используете 8 символов табуляции шириной пробела и отступаете всего одним символом табуляции вместо 1 или более пробелов.

Теоретически кто-то мог бы также написать

      throw
{
        status: "error",
        code: 12,
        details: localvar,
};

что также потерпит неудачу, потому что точка с запятой будет вставлена ​​сразу после ключевого слова из-за приведенных выше правил ASI. В реальном мире все, кажется, пишут throw new ...или же throw localvar.

Я не знаю историю этих исключений, но могу только предположить, что это какая-то историческая ошибка, которую больше нельзя исправить из-за существующего реального кода, зависящего от этой ошибки. Я не вижу ни одной конструкции, в которой эта автоматическая точка с запятой была бы действительно полезной, поэтому я думаю, что это просто ошибка в исторической спецификации. (Код, следующий за returnили же throwне может разумно начинать с литерала объекта, поэтому он все равно не будет работать со вставленной точкой с запятой.)

Другие вопросы по тегам