Вопрос по javascript – Объявления функций внутри операторов if / else?

45

Как обрабатываются объявления функций?

var abc = '';
if(1 === 0){
    function a(){
        abc = 7;
    }
}else if('a' === 'a'){
    function a(){
        abc = 19;
    }
}else if('foo' === 'bar'){
    function a(){
        abc = 'foo';
    }
} 
a();
document.write(abc); //writes "foo" even though 'foo' !== 'bar'

Этот пример производит различные выходные данные в Chrome и Firefox. Хромированные выходыfoo пока FF выводит19.

+1: подтвержденные chrome и firefox дают разные результаты. Jesse Good
@DC_: ссылка дает мне19 в моей консоли (Firefox). Jesse Good
jsfiddle:jsfiddle.net/Mqs8Y DC_
я получил19, Какой двигатель вы используете? Ignacio Vazquez-Abrams
Здесь все двигатели работают правильно. Chrome et al. работать напрямую через спецификацию, и поведение FF является расширением спецификации. То есть он отличается по дизайну. По существу (то есть хром) подъем выполняется и последнийdeclaration выигрывает, но FF реализует то, что они называют операторами функций (терминология iirc), что позволяет оценивать то, что иначе было бы объявлениями. davin

Ваш Ответ

3   ответа
50

ECMAScript 5 (ES5) был распространен. В строгом режиме ES5 объявления функций не могут быть вложены вif блок, как показано в вопросе. В нестрогом режиме результаты были непредсказуемы. Различные браузеры и движки реализовали свои собственные правила для того, как они будут обрабатывать объявления функций внутри блоков.

С 2018 года многие браузеры поддерживают ECMAScript 2015 (ES2015) в той степени, в которойобъявления функций теперь разрешены внутри блоков, В среде ES2015 объявление функции внутри блока будет ограничено внутри этого блока. Код в вопросе приведет к неопределенной ошибке функции, потому что функцияa объявляется только в рамкахif заявления и, следовательно, не существует в глобальной области.

Если вам нужно условно определить функцию, то вы должны использоватьфункциональные выражения.

Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededFunctionStatementError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededthe first example in the question is not legal syntaxError: User Rate Limit Exceeded
7

http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

В JavaScript у вас есть объявление функции:

function foo() {
}

и выражение функции

var foo = function() {
}

Цитировать изhttp://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

“Function declarations and function variables are always moved (‘hoisted’) to the top of their JavaScript scope by the JavaScript interpreter”.

Итак, что произошло в вашем первом примере, это объявление функцииfunction a(), поднимается на вершину области видимости Javascript, таким образом производя 'foo' apos; даже если if оценивается как ложное

Думать оvar foo как обычный оператор Javascript, он выполняется только во время выполнения вашего JavaScript, в отличие отfunction foo()Вот почему действует следующее:

alert(foo());

function foo() {
   return 'gw ganteng';
}

Вот,function foo() разбирается парсером, ставитfoo() в текущей области, прежде чем пытаться позвонитьalert(foo())

http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

In JavaScript execution there is Context (which ECMA 5 breaks into LexicalEnvironment, VariableEnvironment and ThisBinding) and Process (a set of statements to be invoked in sequence). Declarations contribute to the VariableEnvironment when the execution scope is entered. They are distinct from Statements (such as return) and are not subject to their rules of process.

Error: User Rate Limit ExceededlastError: User Rate Limit Exceeded
Error: User Rate Limit ExceededshouldError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
1

чтобы реализации регистрировали все объявления функций и переменных во время первого прохода при входе в любой новый глобальный контекст или контекст выполнения на уровне функций. Хром технически делает это прямо здесь, потому что он смотрит внутрьelse а такжеthen блоки и регистрацияa() до исполнения. К сожалению, это дает самые нечитаемые результаты.

FF ждет, пока он не выполнит оценку оператора if, прежде чем вычислить и добавить объявления функций и переменных в текущий контекст. КСТАТИ. Оба браузера делают это таким образом в предложениях catch и finally.

Это на самом деле просто вопрос двух разных реализаций ECMA, имеющих дело с функцией, которой не должно быть с самого начала. Рассматриваемый сценарий показывает, почему объявления функций не должны находиться внутри операторов потока управления.

Похожие вопросы