Запутанная спецификация EcmaScript — создание экземпляра привязки объявления


Когда я прочитал спецификацию для обучения "поднятию", там FunctionDeclaration происходит на шаге 5, но VariableDeclaration происходит на шаге 8 и я думаю, что это означает, что объявление функции имеет более высокий приоритет, чем объявление переменной.
Как вы думаете, почему декларация функций объявляется первой и есть ли для этого какая-то причина?
Примечание. Эту часть можно прочитать по этой ссылке http://www.ecma-international.org/ecma-262/5.1/#sec-10.5

У меня есть гипотеза для моего вопроса. Это не ответ, это гипотеза, потому что я действительно не знаю ответа на этот вопрос, по-видимому, люди тоже не знают ответа.
Моя гипотеза,
эта функция может переопределить другую функцию, но переменная не может, я думаю, потому что происходит первое объявление функции.


person Murad Sofiyev    schedule 17.08.2019    source источник
comment
Я просто отмечу, что версия 5.1 очень устарела, поскольку ее заменили ES2015, ES2016, ES2017, ES2018 и ES2019. Если вы хотите изучить спецификацию JavaScript, я предлагаю действующую спецификацию.   -  person T.J. Crowder    schedule 18.08.2019
comment
Боюсь, непонятно, о чем вы здесь спрашиваете. Да, шаг 5 создает привязки раньше, чем шаг 8 (на языке этой спецификации). Но... что ты об этом спрашиваешь?   -  person T.J. Crowder    schedule 18.08.2019
comment
@ TJCrowder Я спрашиваю, есть ли для этого причина?   -  person Murad Sofiyev    schedule 18.08.2019
comment
Потому что должен быть порядок...?   -  person T.J. Crowder    schedule 18.08.2019
comment
@ T.J.Crowder Спасибо за ссылку. Я читал по новой ссылке, но не думаю, что в новой спецификации изменился экземпляр привязки декларации )))   -  person Murad Sofiyev    schedule 18.08.2019
comment
Ладно, почему порядок не произошел в обратном порядке. Например, почему VariableDeclaration не произошло до FunctionDeclaration?   -  person Murad Sofiyev    schedule 18.08.2019
comment
Почему в языке X есть функция Y? На вопросы, которые в конечном итоге лучше всего отвечают разработчики языка.   -  person Pointy    schedule 18.08.2019
comment
Хорошо, я ищу любого дизайнера языка здесь )) Вы рекомендуете какой-либо сайт для дизайнеров контактного языка? : д   -  person Murad Sofiyev    schedule 18.08.2019
comment
@MuradSofiyev — его зовут Брендан Эйх, и он достаточно отзывчив в Твиттере, но не в Stack Overflow.   -  person T.J. Crowder    schedule 18.08.2019
comment
@ Скотт Маркус Не обязательно, что он спрашивает, как кричать на ветер. Иногда хочется узнать, почему белый цвет — белый, и в этом нет ничего плохого. У всего есть свое объяснение, даже почему белый цвет — белый.   -  person Noob    schedule 18.08.2019
comment
Было бы полезно, если бы вы объяснили, как бы вы использовали информацию (причину поведения), если бы она была у вас прямо сейчас.   -  person Pointy    schedule 18.08.2019
comment
Я согласен с @Noob. Люди должны задавать вопросы, а не только читать правила. Если какое-либо правило имеет это, это означает, что это правило имеет какую-либо причину. Если одно правило есть без причины, то это правило ложно.   -  person Murad Sofiyev    schedule 18.08.2019
comment
@ Нуб Согласен. Но вопрос был задан и на него был дан ответ, и тем не менее ОП упорствует, таким образом крича на ветер.   -  person Scott Marcus    schedule 18.08.2019
comment
На этот вопрос не дан полный ответ.   -  person Murad Sofiyev    schedule 18.08.2019


Ответы (2)


Есть два варианта: либо этот код недействителен (например, синтаксическая ошибка):

function foo() {
    console.log("foo1");
}
var foo = function() {
    console.log("foo2");
};
foo();

...или порядок вещей. В спецификации JavaScript в этом случае есть порядок вещей:

  1. Объявление функции создает привязку в области видимости для foo, которая регистрирует foo1.
  2. var в var foo = ... не действует, поскольку varAlreadyDeclared имеет значение true.
  3. foo перезаписывается значением, полученным из функционального выражения foo = function() { /*...*/ };

Почему? Потому что так указано. Точнее, потому что объявление функции и оператор var создают изменяемую привязку в контексте выполнения, поэтому привязка создается первой. «Первый» снова нуждается в определении, поэтому выбранное определение заключалось в том, что объявление сначала создает привязку. Но оба создают изменяемые привязки и помните, что часть var foo и часть foo = ... обрабатываются совершенно отдельно. Поскольку объявления функций обрабатываются перед пошаговым выполнением кода, следующее делает то же самое, что и выше:

var foo = function() {
    console.log("foo2");
};
function foo() {
    console.log("foo1");
}
foo();

Хотя объявление функции сначала создает привязку и устанавливает ее для функции, выполняющей console.log("foo1"), часть foo = ... происходит позже и обновляет привязку, чтобы она ссылалась на новую функцию, выполняющую console.log("foo2").

У Брендана Эйха были и другие варианты, но именно этот он сделал в те судьбоносные 10 дней в мае 1995 года. :-) И он действительно логически следует из этих решений:

  1. Объявления функций создают изменяемые привязки
  2. Объявления функций и объявления var создают один и тот же тип привязок
  3. Объявления функций поднимаются (например, функция создается и назначается привязке до начала пошагового выполнения)
  4. Часть объявления var поднимается с использованием значения инициализации undefined, но часть инициализатора var x = y не устанавливается до пошагового выполнения кода.
person T.J. Crowder    schedule 17.08.2019
comment
Иногда я удивляюсь, как мистер Эйх умудрился втиснуть все подобные мелкие решения в такой короткий промежуток времени. - person Pointy; 18.08.2019
comment
@Pointy - Удивительно, что вы можете сделать, когда отбрасываете осторожность на ветер. Кое-что из этого, я подозреваю, было оправдано/кодифицировано задним числом, основываясь на том, что первоначальная реализация в конечном итоге делала почти как побочный эффект «Getting It Done». :-) - person T.J. Crowder; 18.08.2019
comment
Хорошо, давайте думать иначе. Например, этот процесс может происходить и по порядку исходного кода. - person Murad Sofiyev; 18.08.2019
comment
Но вы говорите, что это выбор Бендана, и мы ничего не можем сделать, да? - person Murad Sofiyev; 18.08.2019
comment
@MuradSofiyev изменение чего-то подобного разрушило бы Интернет, потому что это может повлиять на бесчисленные миллиарды строк существующего кода JavaScript. - person Pointy; 18.08.2019
comment
@MuradSofiyev - этот процесс может происходить и по порядку исходного кода Могло бы, но не происходит. Объявления функций поднимаются. Вы говорите, что это выбор Бендана, и мы ничего не можем сделать, да Я понятия не имею, что вы имеете в виду под словом "сделать что-нибудь". Язык определяется спецификацией. У этой спецификации было много входных данных. Один из них (довольно большой) — это то, что Брендан сделал в мае 1995 года. С тех пор обратная совместимость стала довольно важным делом. - person T.J. Crowder; 18.08.2019
comment
Хорошо, это означает, что у нас нет причин для заказа, это выбор Брендана. У нас нет больше информации об этом. Я так понимаю правда? - person Murad Sofiyev; 18.08.2019
comment
@MuradSofiyev - Как я уже сказал, это вытекает из других решений, которые в целом имеют смысл. Но да, время от времени, просто потому, что так оно и есть. :-) (Я не думаю, что это верно в данном конкретном случае, но...) - person T.J. Crowder; 18.08.2019
comment
Круто, я понимаю, что ты имеешь в виду. Я одобряю этот ответ, но это не означает, что спецификация неверна: d - person Murad Sofiyev; 18.08.2019
comment
@MuradSofiyev Того же точного результата можно было бы достичь, сказав, что сначала создаются привязки var, а затем привязки function перезаписывают свои значения. Никакой разницы в коде. - person Bergi; 18.08.2019
comment
@Bergi Но какой-то пример заказа важен - person Murad Sofiyev; 18.08.2019

И объявления функций, и объявления переменных поднимаются.

Сначала поднимаются функции, а затем переменные.

foo(); // 1

var foo;

function foo() {
  console.log(1);
}

foo = function() {
  console.log(2);
};

Обратите внимание, что var foo было дублирующим (и, следовательно, игнорируемым) объявлением, даже несмотря на то, что оно предшествовало объявлению функции.

Также интересен тот факт, что последующие объявления функций переопределяют предыдущие.

foo(); // 3

function foo() {
  console.log(1);
}

var foo = function() {
  console.log(2);
};

function foo() {
  console.log(3);
}

Дополнительную информацию вы можете найти в Вы не знаете JS: Scope & Closures книга

person Community    schedule 17.08.2019
comment
Я знаю, что сначала произошло объявление функции, но мне это интересно, вот почему. Также я читаю YDKJS и задаю этот вопрос @gettify github.com/ getify/Вы-Не-Знаете-JS/issues/1501 - person Murad Sofiyev; 18.08.2019
comment
Я поддерживаю ваш комментарий, потому что вы даете мне представление :) Функция может переопределять себя, но не переменную. Я думаю, что это важный момент для заказа. - person Murad Sofiyev; 18.08.2019
comment
@MuradSofiyev Также имеет смысл отметить, что var a = 11; в основном состоит из двух операторов: var a; (объявление) и a = 11 (присваивание). Поднимаются только объявления, а назначения остаются на месте. - person ; 18.08.2019
comment
Да, это правда - person Murad Sofiyev; 18.08.2019