2015-08-22 2 views
0

MDN приведены некоторые примеры, как показано ниже,объявление функции Vs выражения функции

// function declaration 
function foo() {} 

// function expression 
(function bar() {}) 

// function expression 
x = function hello() {} 


if (x) { 
    // function expression 
    function world() {} 
} 


// function declaration 
function a() { 
    // function declaration 
    function b() {} 
    if (0) { 
     // function expression 
     function c() {} 
    } 
} 

По определению, выражение принимает значение.

Сверху например,

1) Является ли функция world выражение или декларация? Потому что world выглядит как заявление о декларации

2) Является ли функция c выражением или декларацией? Потому что c выглядит как заявление о декларации

3) Как понять синтаксис функции bar в paranthesis? Как var x = (function bar() {return 1}) отличается от var x = function bar() {return 1}?

+0

они оба комментарии выше них говорят, что они являются функцией выражения – DTing

+0

@DTing Но я еще не согласен с этим. – overexchange

+0

@overexchange Объявление функции очень легко (и часто непреднамеренно) превращается в выражение функции. Объявление функции перестает быть одним из следующих: становится частью выражения или больше не является «исходным элементом» функции или самого скрипта. «Исходный элемент» - это не-вложенный оператор в скрипте или в теле функции: – artm

ответ

3

Замечания на странице MDN очень вводят в заблуждение. (MDN является совместно отредактированы ссылки. Это обычно отлично. Иногда он падает немного меньше этого.)

Из выше примера,

1) Является ли функция мира выражение или заявление?

2) Является ли функция c выражением или декларацией?

До ES2015 (так называемый «ES6»), они были оба неопределенного поведения потому что они были объявления функций внутри блока управления потоком. Спецификация не определяла, как их следует обрабатывать, но обработка их была «допустимым расширением» под спецификацией (blech), и некоторые из них поддерживали их. К сожалению, разные двигатели поддерживали их, делая разные вещи.

По ES2015, хотя, спецификация принимает их: Они все еще объявления функций, но как они интерпретируются изменяется в зависимости от того, ...

  • ... код в строгом режиме (в котором поведение является рациональным и straightfoward),
  • ... код находится в свободном режиме на браузер размещается двигатель JavaScript, который реализует опционального унаследованного поведения, описанное Annex B.3.3 и Annex B.3.4 в спецификации (путают, и есть только несколько сценариев, которые afe cross-browser),
  • ... или код находится в свободном режиме в браузере без JavaScript, который в теории не должен реализовывать Приложение   B (но это не останавливает их).

Поскольку в свободном режиме вы не можете быть уверены в том, будет ли двигатель JavaScript, чтобы реализовать приложение   поведения B или поведение, не включенных в приложение   B, единственные разумные варианты:

  • Используйте строгий режим, или
  • Не используйте объявления функции уровня блока.

Если вы используете строгий режим (будь то в браузере или нет), то поведение довольно проста: Декларация поднимается к верхней части своего блока и блок-Scoped (как let и const являются). Идентификатор, созданный объявлением, доступен для записи, и поэтому он равен , как будто декларация была преобразована в выражение функции, назначенное переменной let в верхней части блока. Возьмем пример world, но добавим его.

Это:

"use strict"; 
// ... 
function example() { 
    if (x) { 
     console.log("testing:"); 
     console.log("1:", typeof world); 
     function world() {} 
     console.log("2:", typeof world); 
    } 
    console.log("3":, typeof world); 
    console.log("4:", world === undefined); 
} 

... эффективно становится этим:

"use strict"; 
// ... 
function example() { 
    if (x) { 
     let world = function world() {}; 
     console.log("testing:");    // testing: 
     console.log("1:", typeof world);  // 1: function 
     console.log("2:", typeof world);  // 2: function 
    } 
    console.log("3:", typeof world);  // 3: undefined 
    console.log("4:", world === undefined); // ReferenceError: `world` is not defined 
} 

Обратите внимание, как declaraton был поднят в верхней части блока, и блок-область видимости.

Вне строгого режима, опять же, это зависит, но, не наследие версия так же, как строгий режим но с var вместо let.

Итак: это:

Это:

// NOT in strict mode 
function example() { 
    if (x) { 
     console.log("testing:"); 
     console.log("1:", typeof world); 
     function world() {} 
     console.log("2:", typeof world); 
    } 
    console.log("3":, typeof world); 
    console.log("4:", world === undefined); 
} 

... эффективно становится этим:

// NOT in strict mode 
function example() { 
    var world; 
    if (x) { 
     world = function world() {}; 
     console.log("testing:");    // testing: (if executed) 
     console.log("1:", typeof world);  // 1: function (if executed) 
     console.log("2:", typeof world);  // 2: function (if executed) 
    } 
    console.log("3:", typeof world);  // 3: function if `x` is truthy, undefined if `x` is falsy 
    console.log("4:", world === undefined); // 4: false if `x` is truthy, true if `x` is falsy 
} 
+0

Но язык агностически выражает значение. Таким образом, назначение функции можно рассматривать как выражение. В python 'if 1: def f(): pass', Является ли' f' выражением или декларацией? – overexchange

+0

@overexchange: Я не занимаюсь Python, я боюсь, что не знаю, что вы задаете в этом вопросе. –

+0

Итак, 'world' и' c' находятся в локальном контексте. Можете ли вы также ответить на мой третий вопрос? – overexchange

Смежные вопросы