Функции Javascript, такие как "var foo = function bar()..."?
Код выглядит следующим образом (синтаксис может показаться странным, но, насколько я знаю, нет ничего плохого в нем или нет?)
var add=function addNums(a, b) {
return a+b;
}
alert("add: "+ add(2,3)); // produces 5
alert("addNums: "+addNums(2,3)); // should also produce 5
addNums()
объявляется как функция. Поэтому, когда я передаю ему параметры, он также должен возвращать результат.
Тогда почему я не получаю второе поле предупреждения?
Ответы
Ответ 1
Вы видите имя функции function (NFE).
Анонимное выражение функции - это то, где вы назначаете функцию без имени переменной 1:
var add = function () {
console.log("I have no own name.");
}
Именованное функциональное выражение - это то, где вы назначаете именованную функцию переменной (сюрприз!):
var add = function addNums() {
console.log("My name is addNums, but only I will know.");
}
Имя функции доступно только в самой функции. Это позволяет использовать рекурсию, не зная "внешнее имя" функции - даже без необходимости устанавливать ее в первую очередь (подумайте о функциях обратного вызова).
Выбираемое имя затеняет существующее имя, поэтому, если другой addNums
определен в другом месте, он не будет переопределен. Это означает, что вы можете использовать любое имя, которое вам нравится, не опасаясь проблем, связанных с определением области видимости, или ничего не сломать.
В прошлом вы использовали arguments.callee
, чтобы ссылаться на функцию внутри себя, не зная ее имени. Но поддержка этого удаляется из JavaScript 2 поэтому NFE - правильный способ сделать это в настоящее время.
Здесь много материала для чтения по теме: http://kangax.github.io/nfe/
1 Присвоение переменной переменной необязательно, она просто служит примером, чтобы отличить ее от объявления простой функции. Это может быть любой другой контекст, в котором JS ожидает выражение (например, аргумент функции).
2 Вы получите сообщение об ошибке, если у вас есть строгий режим и попробуйте использовать arguments.callee
.
Ответ 2
Проблема
Вы используете выражение named function - и имя выражения функции не доступно вне области этой функции:
// Function statement
function statement() {
console.log("statement is a type of " + typeof statement);
}
statement();
console.log("statement is a type of " + typeof statement);
приводит к:
statement is a type of function
statement is a type of function
тогда:
// Function expression with a name
var expression = function namedExpression() {
console.log("namedExpression is a type of " + typeof namedExpression);
};
expression();
// namedExpression(); // uncommenting this will cause an exception
console.log("expression is a type of " + typeof expression);
console.log("namedExpression is a type of " + typeof namedExpression);
будет производить:
namedExpression is a type of function
expression is a type of function
namedExpression is a type of undefined
Решение
В зависимости от того, что вы пытаетесь сделать, вы хотите сделать одно из следующего:
-
Измените объявление функции, чтобы использовать оператор, а затем псевдоним вашей функции:
function addNums(a, b) {
return a + b;
}
var add = addNums;
-
Имени обоих имен в ваше выражение:
var add = addNums = function addNums(a, b) {
return a + b;
};
Почему JavaScript делает так?
Именованные функциональные выражения полезны, потому что они позволяют ссылаться на функцию внутри себя, и они дают вам имя для поиска в отладчике. Однако, когда вы используете функцию как значение, вы, как правило, не хотите, чтобы части ее протекали в охватывающую область. Рассмотрим:
(function setup() {
var config = retrieveInPageConfig();
if (config.someSetting) {
performSomeOtherSetup();
}
kickOffApplication();
})();
Это вполне законное использование выражения функции - в таком случае вы не ожидаете, что имя setup
будет протекать в охватывающей области. Присвоение названного выражения функции переменной является лишь частным случаем этого, что просто выглядит как объявление оператора функции.
Ответ 3
addNums
доступен только в области новой функции.
Совершенно очевидно, что когда выражение функции имеет имя (технически - Идентификатор), он называется выражением функции с именем функции. Что вы в первом примере - var bar = function foo() {}; - был именно это - выражение с именованной функцией с функцией foo, являющейся функцией имя. Важно помнить, что это имя только доступен в области вновь определенной функции; спецификация мандата, который идентификатор не должен быть доступен для охватывающей области.
Подробнее о форме в этой статье.
Ответ 4
Вы должны либо объявить как именованную функцию:
function addNums(){
}
или назначить функцию переменной:
var add= function(){// your code }
Причина, по которой addNum() ничего не возвращает, состоит в том, что она не добавляется в глобальную область с тем, как вы ее объявляете.
Ответ 5
Демо
function addNums(a, b) {
return a+b;
}
var add = addNums;
alert("add: "+ add(2,3));
alert("addNums: "+addNums(2,3));
Ответ 6
Я добавил свой код в свое тестовое веб-приложение и отлично справляюсь со мной. Вот код. Не могли бы вы поделиться более подробной информацией о своем коде/приложении?
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JavascriptTest.aspx.cs" Inherits="GetGridViewColumnValue.JavascriptTest" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
var add = function addNums(a, b) {
return a + b;
}
alert("add: " + add(2, 3)); // produces 5
alert("addNums: " + addNums(2, 3));
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
Ура!!!
Ответ 7
Рассмотрим следующий код:
var f = function g() {
// function
};
g
будет доступен только в самой функции, и это необходимо, если вы хотите использовать функцию
само по себе, для записи рекурсивных функций. Например, вам нужна функция factorial
:
var f = function factorial(x) {
if (x <= 1) return 1;
// here we want to use the function itself
return x * factorial(x - 1);
};
console.log(f(5));
Однако, это действительно необходимо, поскольку вы можете получить доступ к самой функции с помощью arguments.callee
:
// note that the function has not any name
var f = function (x) {
if (x <= 1) return 1;
// here we want to use the function itself
return x * arguments.callee(x - 1);
};
console.log(f(5));
Ответ 8
Я немного изменил ваш код:
var add = function addNums(a, b){
return a+b;
}
console.log(add);
console.log(typeof(add));
console.log("add: "+ add(2,3)); // produces 5
console.log("addNums: "+addNums(2,3));
И затем начал запускать его внутри node.js, чтобы получить этот вывод:
[Function: addNums]
function
add: 5
/home/mel/l.js:44
console.log("addNums: "+addNums(2,3));
^
ReferenceError: addNums is not defined (... backtrace)
Обычно переменная, назначенная встроенным анонимным методом, выводит [Function]
при вызове с помощью console.log(var);
Здесь console.log(add);
приводит к тому, что имя также печатается.
Значит, это не так, как ваше объявление addNums является недопустимым или не используется, оно просто ограничено привязкой к переменной add.
Ответ 9
addNums не является функцией в глобальном пространстве имен.
Это функция, определенная только внутри оператора присваивания.
если вы хотите получить к нему доступ, выполните следующие действия:
function addNums(a, b)
{
return a+b;
}
var add = addNums;
var add = function <---- the function name is add and it value is a function..