именованная функция присваивает переменной [duplicate]

UPDATE t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
SET t1.a = 'something',
    t2.b = 42,
    t3.c = t2.c
WHERE t1.a = 'blah';

Чтобы узнать, что он собирается обновить, вы можете преобразовать это в оператор select, например :

SELECT t2.t1_id, t2.t3_id, t1.a, t2.b, t2.c AS t2_c, t3.c AS t3_c
FROM t1
INNER JOIN t2 ON t2.t1_id = t1.id
INNER JOIN t3 ON t2.t3_id = t3.id
WHERE t1.a = 'blah';
78
задан Mark Amery 13 September 2017 в 21:35
поделиться

5 ответов

В случае анонимного выражения функции функция анонимна & nbsp; & mdash; буквально, у него нет имени. Переменная, которую вы назначаете, имеет имя, но функция не работает. (Обновление: это было верно через ES5. Начиная с ES2015 [aka ES6], часто функция, созданная с анонимным выражением, получает истинное имя, читается далее ...)

Имена полезны. Имена можно увидеть в трассировках стека, столах вызовов, списках точек останова и т. Д. Имена - это Good Thing ™.

Вам нужно остерегаться именованных функциональных выражений в более старых версиях IE (IE8 и ниже) , потому что IE ошибочно создает два полностью отдельных объекта функции в два совершенно разных раза (больше в моей статье в блоге Double take ). Если вам нужно поддерживать IE8, лучше всего использовать анонимные выражения функций или функции declarations , но избегать названных функциональных выражений.

Как и в ES2015, анонимные "выражения функций создают функции с именами, и это было обусловлено тем, что различные современные механизмы JavaScript были достаточно умны в определении имен из контекста. В ES2015 выражение анонимной функции приводит к функции с именем boo. Это разбросано по всему spec , а не определено в одном месте с кучей правил: Поиск вхождения «SetFunctionName», в настоящее время найденный в:

Краткая версия в основном в любое время, когда выражение анонимной функции появляется справа от чего-то вроде назначение или инициализацию, например:

var boo = function() { /*...*/ };

(или это могут быть let или const, а не var) или

var obj = {
    boo: function() { /*...*/ }
};

или

doSomething({
    boo: function() { /*...*/ }
});

(последние два - это одно и то же) , результирующая функция будет иметь имя (boo в примерах).

Существует важное и преднамеренное исключение: Назначение ap rperty на существующем объекте:

obj.boo = function() { /*...*/ }; // <== Does not get a name

Это было из-за проблем с утечкой информации, возникающих при добавлении новой функции в процессе добавления; подробности в моем ответе на другой вопрос здесь .

74
ответ дан T.J. Crowder 16 August 2018 в 10:34
поделиться
  • 1
    И на самом деле, следующая версия спецификации ES6 будет включать в себя правила для вывода имени функции, основанной на переменной или свойстве, присваиваемом ей , - это все еще верно? Я не читал (длинный) черновик спецификации, но пытался использовать CTRL-F для этих правил и не мог найти их. Возможно, есть ссылка на соответствующий раздел? – Mark Amery 19 February 2015 в 01:20
  • 2
    Стоит отметить, что есть по крайней мере два места, в которых использование NFE по-прежнему дает конкретные преимущества: во-первых, для функций, предназначенных для использования в качестве конструкторов с помощью оператора new (предоставление всех имен таких функций делает свойство .constructor более полезным при отладке для выяснения того, какой черт какой-то объект является экземпляром), а для литералов функций передается непосредственно в функцию без предварительного присвоения свойства или переменной (например, setTimeout(function () {/*do stuff*/});). Даже Chrome показывает их как (anonymous function), если вы не поможете ему, назвав их. – Mark Amery 19 February 2015 в 01:25
  • 3
    @MarkAmery: "это все еще верно? Я ... пытался использовать CTRL-F для этих правил и не мог найти их. О да. :-) Он разбросано по всей спецификации, а не находится в одном месте, определяя набор правила, просто найдите «setFunctionName». Я добавил небольшое подмножество ссылок выше, но в настоящее время он появляется в ~ 29 разных местах. Я был бы слегка удивлен, если бы ваш пример setTimeout не захватил имя из формального аргумента, объявленного для setTimeout, если бы он был один. :-) Но да, NFE определенно полезны, если вы знаете, что не будете иметь дело со старыми браузерами, которые делают хэш из них. – T.J. Crowder 19 February 2015 в 10:18

Вы всегда должны использовать выражения функции NAMED.

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

2.Анонимные функции не 't помогает при отладке, поскольку вы не можете увидеть имя функции, которая вызывает проблемы.

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

var foo = function bar() {
 //some code...
};
foo();
bar(); // Error!

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

0
ответ дан lux 16 August 2018 в 10:34
поделиться

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

Например , рассмотрим этот код:

setTimeout(function sayMoo() {
    alert('MOO');
    setTimeout(sayMoo, 1000);
}, 1000);

Невозможно было бы написать этот код достаточно чисто, если бы выражение функции, переданное в setTimeout, было анонимным; мы должны были бы назначить его переменной вместо перед вызовом setTimeout. Таким образом, с выражением с именем функции, немного короче и аккуратнее.

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

setTimeout(function () {
    alert('MOO');
    setTimeout(arguments.callee, 1000);
}, 1000);

... но arguments.callee устарел и категорически запрещен в строгом режиме ES5. Поэтому MDN советует:

Избегайте использования arguments.callee() либо , давая функциональным выражениям имя , либо используйте объявление функции, в котором функция должна вызывать себя.

< / blockquote>

(основное внимание)

21
ответ дан Mark Amery 16 August 2018 в 10:34
поделиться

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

Он будет доступен только внутри функции (кроме IE8 -).

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

Обратите внимание, что с объявлением функции это невозможно. Это «специальное» имя внутренней функции указывается только в синтаксисе Function Expression.

var f = function sayHi(name) {
  alert( sayHi ); // Inside the function you can see the function code
};

alert( sayHi ); // (Error: undefined variable 'sayHi')

Кроме того, имя NFE (Именованное выражение) не может быть перезаписано:

var test = function sayHi(name) {
  sayHi = "тест"; // try to redefine
  alert( sayHi ); // function... (redefinition is unsuccessful )
};

test();
3
ответ дан Roman 16 August 2018 в 10:34
поделиться

Использование названных функциональных выражений лучше, если вы хотите иметь возможность ссылаться на рассматриваемую функцию, не полагаясь на устаревшие функции, такие как arguments.callee.

1
ответ дан Sudhir Bastakoti 16 August 2018 в 10:34
поделиться
  • 1
    Это скорее комментарий, чем ответ. Возможно, разработка была бы полезной – vsync 3 July 2016 в 21:08
Другие вопросы по тегам:

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