Вопрос по javascript – В чем разница между выражением функции и объявлением в JavaScript? [Дубликат]

452

This question already has an answer here:

var functionName = function() {} vs function functionName() {} 37 answers

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

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

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

//Named function expression
var foo = function foo() { return 5; }
</code>
What is a named/anonymous function expression? What is a declared function? How do browsers deal with these constructs differently?

Что означают ответы на аналогичный вопрос (var functionName = function () {} против функции functionName () {}) не совсем точно понял?

Здесь & APOS; sa good article on named function expressions, Выражения функций против объявлений рассматриваются в первом разделе. Evan Meagher
Основным отличием ИМО является подъем. Вот хорошая статья на эту тему:adequatelygood.com/JavaScript-Scoping-and-Hoisting.html Ryan Wheale

Ваш Ответ

5   ответов
1

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

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

99
Function Declaration
function foo() { ... }

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

Function Expression

Named Function Expression

var foo = function bar() { ... }

Anonymous Function Expression

var foo = function() { ... }

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

Immediately-Invoked Function Expression (IIFE)
(function() { ... }());
Conclusion

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

Вас такжеcan Именованные IIFE:(function myFunc() { ... }());
Интересное место: js чувствителен к регистру. Ваши примеры с заглавными буквами не работают ;-)
@naXa - +1 за ссылку, хорошо написанная статья о IIFE :)
Более короткий и широко используемый способ написания IIFE: если вас не волнует возвращаемое значение или возможность сделать ваш код немного сложнее для чтения, вы можете сохранить байт, просто добавив префикс функции унарному оператору. Пример:!function(){ /*code*/ }(); (источник:linked article)
Добро пожаловать в переполнение стека! Спасибо за публикацию вашего ответа! Пожалуйста, не забудьте прочитатьFAQ on Self-Promotion внимательно. Также обратите внимание, что этоrequired что вы публикуете заявление об отказе от ответственности при каждой ссылке на свой собственный сайт / продукт.
384

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

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

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

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

Example: Function Expression

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

Example: Function Declaration

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


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

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

Последний не такой, какvar foo = function() { return 5; }, Потому что здесьfoo.name является''в последнем'foo'.
@ZachL. В качестве примера я хотел бы сказать, что вторая функция имеет имя, а первая - нет.
& quot; Но если вы вызываете объявление функции, оно всегда будет работать. & quot; Так есть ли польза от использования выражения функции? Почему бы просто не всегда использовать объявления?
Фактически считается наилучшей практикой использовать выражения функций, поскольку тогда поведение является более интуитивным, чем с объявлениями. Он читается лучше, поскольку он следует логическому потоку. Вы определяете его, а затем вызываете его, если вы не получили ошибку, которая является ожидаемым поведением. На самом деле я думаю, что объявления функций недопустимы в не функциональных областях ... Я рекомендую этот пост на эту тему:javascriptweblog.wordpress.com/2010/07/06/…
@JCM AFAIK, свойство name не является частью ECMAScript и реализовано только в некоторых браузерах.Function.name at MDN
10

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

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

EDIT:

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

END EDIT

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

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

Такой же как

var foo = function fooYou() { return 5; }
Кроме того, выражения именованных функций полезны для отладки:var foo = function fooYou() { return 5; }; console.log(foo); console.log(foo.name); распечатаетfooYou() / fooYou (Fire Fox),[Function: fooYou] / fooYou (Node.js),function fooYou() { return 5; } / fooYou (Chrome) или что-то в одиночку эти строки, в зависимости от того, где вы выполняете это.
fooYou не игнорируется Он виден в теле функции, поэтому функция может ссылаться на себя (например, для реализации рекурсии).
Выражения именованных функций - это рекомендуемая практика, поскольку она позволяет вам обращаться к функции внутри себя, если вам это нужно. Например, чтобы вызвать функцию рекурсивно или иметь дело с ее именем или свойствами. Кстати, главное преимущество - это отладка. Если вы используете неназванные функции, трудно отладить, если что-то случится прямо здесь, так как вы получите ссылку на анонимную функцию, а не ее имя
Это хороший момент. Я не думал об этом :)
20

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
Вам не нужно объявлять функцию с другим именем, чтобы сделать ее рекурсивной. Фактически, я бы сказал, что это сбивает с толку.a = function a(i) и делатьreturn a(++i) дает тот же результат
Но использование другого имени для функции, нежели переменная, иллюстрирует эту точку более четко. Престижность за предоставление примера использования выражений именованных функций.

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