Знайте выражение JavaScript Function Expression vs Function Declaration, но что это? Именованное выражение функции?

Возможный дубликат:
JavaScript: var functionName = function() {} vs function functionName() {}
В чем отличие выражения функции от объявления в Javascript?

Я знаю различия между декларациями функций и выражениями, но столкнулся с этим кодом с использованием имени функции и хочу понять, что происходит, когда мы запускаем его:

var abc = function def() {
    console.log("Wait! What??");
}

Я знаю, что это не способ JavaScript, но просто хочу знать несколько вещей:

  • Что происходит с abc? Почему это работает? abc можно вызвать, но не def, почему?
  • Является ли это объявлением функции или выражением?
  • def undefined - почему? Если это так, утечки памяти?
  • Почему abc.prototype есть функция def?

Спасибо

Ответы

Ответ 1

Что происходит с abc?

Он содержит объект функции. Если вы ничего не делаете с этим, это будет сбор мусора.

Почему это работает?

Почему бы и нет? Что "работает"?

abc может быть вызван, но не def, почему?

Это справедливо только извне, а не в IE. См. Ниже.

Является ли это объявлением функции или выражением?

Это выражение функции. Вы можете легко увидеть, что, поскольку это часть выражения присваивания; декларации всегда должны быть на верхнем уровне (функций или глобального кода)

def undefined - почему?

Только со стороны. Выражение функции не создает переменные. "def" - ​​это name функции, а внутри функции она также является ссылкой на функцию. Это позволяет рекурсию, например, без использования каких-либо внешних переменных.

var abc = function def() {
    def === abc; // true
    def.name; // "def"
}
abc();
def; // undefined

Если это предполагается, есть ли утечки памяти?

Да, в Internet Explorer. Он создает две различные функции из этого кода. Подробнее см. http://kangax.github.com/nfe/#jscript-bugs

Почему abc.prototype является функцией def?

Это не так. Это просто объект. Возможно, это показано с этим именем в вашей консоли, так как оно относится к функции с именем "def".

Ответ 3

Это Выражение функции 2

Выражения функции могут также иметь имена; имена выражений функций находятся только в области действия в теле функции 1. (Поскольку ECMAScript 5th edition обесценивает arguments.callee, это единственный простой способ записи рекурсивной "анонимной" функции.)

Поскольку это выражение функции, имя не может 1 вводить новое связывание во внешней области.

Кроме того, все функции являются объектами в JavaScript. В f(..), f оценивается до того, как он "вызывается" с помощью (..); если f не оценил функцию, тогда возникает ошибка. Вот почему обратные вызовы, которые являются просто функциями, могут быть названы переменными и переданы как параметры.

Кроме того, проверьте предположение/утверждение о прототипе:

var abc = function def() {}
abc.prototype === abc // -> false
abc.name              // -> "def"

1 См. ответ Берги.

2 Как легко сказать, что это?

Правила грамматики позволяют анализировать только function .. как декларацию функции, если она является SourceElement, хотя большинство движков все еще [неправильно] проанализируйте объявление функции как Statement. Произведения SourceElement выполняются только на "блоке" верхнего уровня программы или на "блоке" верхнего уровня для функции.

В любом случае, когда есть function .., который появляется в месте, которое требует Expression, оно будет анализироваться как функция Expression. Примеры, которые все анализируются как выражения функций:

// Can only assign values: Statements do not have values!
var f = function () {}        
var g = function gName () {}  // see Bergi answer

// Can only pass values: Statements do not have values!
doIt(function () {})          // callback / "anonymous function"

// IIFE: Immediately-Invoked Function Expression
;(function () {})()           // standard IIFE
;(function () {} ())          // alternative standard IIFE
;+function () {} ()           // curious way to write an IIFE
// basically you can use any unary operator to turn it into an expression not only
//  + but also - ! ~ and so on which will modify the return value accordingly

Дело в том, что в каждом из приведенных выше случаев function .. появляется в месте грамматики, требующем выражения и, таким образом, анализируется как выражение функции. (Точки с запятой в начале строк выше избегают "двусмысленности" с ASI, что требуется при написании в стиле без запятой, как я предпочитаю.)

Однако. ;function () {} () и ;function f () {} () являются недопустимым синтаксисом - почему?; -)

Ответ 4

Это именованное функциональное выражение.

В отличие от деклараций функций Идентификатор выражения функции не является обязательным.

Ваша функция def не вызывается сразу - вся функция передается в abc и должна быть явно вызвана abc().

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

ПРИМЕЧАНИЕ. Идентификатор в выражении Function можно ссылаться из внутри функции FunctionExpression FunctionBody, чтобы функция называть себя рекурсивно. Однако, в отличие от FunctionDeclaration, Идентификатор в выражении Function не может ссылаться и не влияет на область применения Expression.

Все последние браузеры обрабатывают это правильно, поэтому вам не нужно беспокоиться об утечке памяти или других странных вещах (некорректная обработка выполняется только в старом IE <= 8).

Ответ 5

Ваш пример - это выражение с именем (named).

Разница между ними заключается в том, как браузер загружает их.

Объявления функций загружаются до, любой код выполняется.
Выражения функции загружаются только , когда интерпретатор достигает этой строки кода.

Это означает:

abc();
var abc = function() {
    console.log("Wait! What??");
}

Не работает, но:

def();
function def() {
    console.log("Wait! What??");
}

Will.

Теперь в вашем примере вы можете получить доступ к def, но только внутри самой функции.

var abc = function def() {
    console.log(def);
}
abc();

// Logs:
//function def() {
//    console.log(def);
//}