Подтвердить что ты не робот

Являются ли именованные функции предпочтительнее анонимных функций в JavaScript?

Возможный дубликат:
JavaScript: var functionName = function() {} против функции functionName() {}

Есть два возможных метода извлечения функции из Javascript:

var foo = function() { ... }

Это немного надумано; Другой распространенный шаблон:

var foo = {
   baz: 43,
   doSomething: function() {
       // ...
   }
}

против

function foo() { 
  // ... 
}

Есть ли явная причина отдать предпочтение одному или другому?

4b9b3361

Ответ 1

Все зависит от того, где вы заявляете свои функции; Подъемный.

Объявления функций и объявления переменных всегда перемещаются ( "поднимаются" ) невидимо в верхнюю часть их области с помощью интерпретатора JavaScript. Функциональные параметры и языковые имена, очевидно, уже есть. Это означает, что код такой:

function foo() {
    bar();
    var x = 1;
}

фактически интерпретируется следующим образом:

function foo() {
    var x;
    bar();
    x = 1;
}

Обратите внимание, что часть присваивания деклараций не была поднята. Только имя поднимается. Это не относится к объявлениям функций, в которых также будет поднято тело всей функции.

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();

В этом случае только объявление функции имеет свое тело, поднятое вверх. Имя "foo" поднимается, но тело остается позади, которое должно быть назначено во время выполнения.

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

foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
bin(); // ReferenceError "bin is not defined"

var foo = function () {}; // anonymous function expression ('foo' gets hoisted)
function bar() {}; // function declaration ('bar' and the function body get hoisted)
var baz = function bin() {}; // named function expression (only 'baz' gets hoisted)

foo(); // valid
bar(); // valid
baz(); // valid
bin(); // ReferenceError "bin is not defined"

Итак, если вы предпочитаете, чтобы функции поднимались вверх, используйте function declaration, иначе используйте expression. Я предпочитаю последнее, поскольку я обычно строю объектные литералы с помощью методов function expressions.

Именованный function expressions может пригодиться при возникновении ошибок. Консоль скажет вам, что это за функция, вместо того, чтобы указывать anonymous aka трассировку стека.

Ответ 2

Здесь вы затронули несколько разных вещей, но я постараюсь сначала ответить на ваш главный вопрос.

В общем....

function() {... } является выражением функции. Синтаксически это на том же уровне, что и 2 или [4,5]. Это представляет ценность. Таким образом, var foo=function(){... } будет работать, как и планировалось, каждый раз.

function foo() {... } является объявлением функции. Может показаться, что это делает то же самое, что и var foo=function(){...}, но есть небольшая оговорка. Как и его объявление, оно работает аналогично концепции подъема переменных в JS (в основном, все объявления переменных выполняются до того, как какие-либо выражения будут оценены).

Хороший пример отсюда:

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();

По существу, переменное поднятие подняло значение до вершины, поэтому этот код эквивалентен (теоретически):

function test() {
    var foo;//foo hoisted to top
    var bar=function(){//this as well
        alert("this will run!");
    }

    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
}

NB: Я хотел бы воспользоваться этим замечанием, чтобы сказать, что интерпретаторам JS трудно следовать теории, поэтому не рекомендуется доверять им несколько сомнительное поведение. Здесь вы найдете хороший пример в конце раздела, где теория и практика в конечном итоге не работают (есть также еще некоторые подробности по теме выражений против объявлений).

Интересный факт: function foo() {...} в скобках преобразует его из объявления в выражение, что может привести к некоторому странному виду кода, например

(function foo() { return 1; })();// 1
foo; //ReferenceError: foo is not defined

Не делайте этого, если у вас нет причин, пожалуйста.


Резюме var foo=function(){... } - это * sorta kinda * то же самое, что и функция foo(){... } за исключением того, что первый делает то, что, как вы думаете, он делает там, где вы думаете, а второй странные вещи если вы не заключаете это в скобки, но это портит область видимости, и интерпретаторы JS позволяют вам делать вещи, которые в спецификации рассматриваются как синтаксические ошибки, так что вы можете поверить, что неправильные вещи на самом деле правильные и т. д....

пожалуйста, используйте выражения функций (var f=function(){...}). Нет реальной причины не делать этого, особенно если учесть, что вы вынуждены это делать, когда используете точечный синтаксис.


На второй вещи вы коснулись.....

Я не совсем уверен, что сказать, это своего рода совершенно отличается от всего остального по этому поводу.

var foo = {
    baz: 43,
    doSomething:function() {
        ...
    }
}

это известно как буквальный синтаксис объекта. JSON, основанный на этом синтаксисе, является довольно аккуратным способом форматирования данных, и этот синтаксис в JS часто используется для объявления новых объектов, например, для одноэлементных объектов (избегая всего беспорядка с объявлением функции и использованием new), Он также может быть использован таким же образом, как XML, и предпочитают все крутые дети...

В любом случае, в основном объектный литеральный синтаксис работает так:

{ name1: val1, .... namek:valk }

Это выражение является объектом с определенными значениями, инициализированными на нем. Таким образом, var obj={ name1: val1,.... namek:valk } означает, что:

obj.name1==val1;
obj['name1']==val1;// x['y'] is the same thing as x.y 
...
obj.namek==valk;

Так какое отношение это имеет к нашему примеру? В основном ваше выражение часто используется для объявления одноэлементных объектов. Но его также можно использовать для объявления прототипа объекта, так что кто-то может позже сделать var newObj = Object.create(foo), и у newObj будет foo в качестве прототипа.

Посмотрите подробно на наследование прототипов, если вы действительно хотите понять, насколько оно полезно. Дуглас Крокфорд подробно рассказывает об этом в одном из своих многочисленных выступлений).

Ответ 3

Существует несколько преимуществ функций именования

  • имена метаанализа. functionInstance.name покажет вам имя.
  • Что еще более важно, имя будет напечатано в трассировке стека.
  • имена также помогают записывать самостоятельно документирующий или грамотный код.

Существует один недостаток названных выражений функций

  • IE имеет утечки памяти для NFE

Нет недостатков в функциях деклараций, кроме менее стилистического управления

Ответ 4

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

Именованный vs анонимный

@Райнос подчеркивает основные моменты. Лучшая часть названных функций состоит в том, что они будут отображаться в трассировке стека. Даже в ситуациях, когда функции присваиваются переменным/свойствам, неплохо дать своим функциям имя, чтобы помочь с отладкой, однако я бы не сказал, что анонимные функции вообще злы. Они служат прекрасной цели:

Являются ли анонимные функции плохой практикой в ​​JavaScript?

Объявление функции vs выражение функции

В этой части вопроса я хотел бы направить вас к этому вопросу, поскольку он, вероятно, охватывает тему гораздо глубже, чем я могу

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