В чем разница между выражением функции и объявлением в JavaScript?

В чем разница между следующими строками кода?

//Function declaration
function foo() { return 5; }

//Anonymous function expression
var foo = function() { return 5; }

//Named function expression
var foo = function foo() { return 5; }
  • Что такое выражение функции named/anonymous?
  • Что такое объявленная функция?
  • Как браузеры имеют дело с этими конструкциями по-другому?

Каковы ответы на аналогичный вопрос (var functionName = function() {} vs function functionName() {}) не получается точно?

Ответ 1

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

Загрузка объявлений функций перед выполнением любого кода.

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

Итак, если вы попытаетесь вызвать выражение функции перед его загрузкой, вы получите сообщение об ошибке! Если вы вызовете объявление функции вместо этого, оно всегда будет работать, потому что никакой код не может быть вызван до тех пор, пока все объявления не будут загружены.

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

alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; } 

Пример: Объявление функции

alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; } 


Что касается второй части вашего вопроса:

var foo = function foo() { return 5; } действительно то же самое, что и два других. Это просто, что эта строка кода использовала, чтобы вызвать ошибку в сафари, хотя она больше не делает.

Ответ 2

Объявление функции

function foo() { ... }

Из-за функции hoisting функция, объявленная таким образом, может вызываться как после, так и перед определением.

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

  • Выражение имен и имен

    var foo = function bar() { ... }
    
  • Анонимная функция

    var foo = function() { ... }
    

foo() можно вызвать только после создания.

Выражение выраженной функции (IIFE)

(function() { ... }());

Заключение

Crockford рекомендует использовать выражение функции, поскольку он ясно показывает, что foo - это переменная, содержащая значение функции. Ну, лично я предпочитаю использовать Декларацию, если нет причин для выражения.

Ответ 3

Относительно третьего определения:

var foo = function foo() { return 5; }

Вот пример, который показывает, как использовать возможность рекурсивного вызова:

a = function b(i) { 
  if (i>10) {
    return i;
  }
  else {
    return b(++i);
  }
}

console.log(a(5));  // outputs 11
console.log(a(10)); // outputs 11
console.log(a(11)); // outputs 11
console.log(a(15)); // outputs 15

Изменить: более интересный пример с закрытием:

a = function(c) {
 return function b(i){
  if (i>c) {
   return i;
  }
  return b(++i);
 }
}
d = a(5);
console.log(d(3)); // outputs 6
console.log(d(8)); // outputs 8

Ответ 4

Первое утверждение зависит от контекста, в котором он объявлен.

Если он объявлен в глобальном контексте, он создаст подразумеваемую глобальную переменную, называемую "foo", которая будет переменной, указывающей на функцию. Таким образом, вызов функции "foo()" может быть сделан где угодно в вашей программе javascript.

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

EDIT:

Я должен был также сказать, что операторы функций (первая) анализируются перед выражениями функций (остальные 2). Это означает, что если вы объявите функцию в нижней части вашего script, вы все равно сможете использовать ее вверху. Выражения функции оцениваются только по мере того, как они попадают в исполняемый код.

END EDIT

Заявления 2 и 3 в значительной степени эквивалентны друг другу. Опять же, если они используются в глобальном контексте, они будут создавать глобальные переменные, и если они используются в закрытии, будут созданы локальные переменные. Однако стоит отметить, что оператор 3 будет игнорировать имя функции, поэтому в общем случае вы можете вызвать функцию что угодно. Поэтому

var foo = function foo() { return 5; }

То же, что и

var foo = function fooYou() { return 5; }

Ответ 5

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

Чтобы помочь вам разобраться, посмотрите на этот показатель test, который нарушил предположение, что я сделал из объявленных внутри себя функций, которые не нуждаются в повторной - создается машиной при вызове внешней функции. Вид стыда, так как мне нравилось писать код таким образом.