Функции 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()
объявляется как функция. Поэтому, когда я передаю ему параметры, он также должен вернуть результат.
тогда, почему я не получаю второе окно предупреждения?
9 ответов
вы видите выражение именованной функции (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
ссылаться на функцию внутри себя, не зная ее имени. Но поддержка это удаляется из JavaScript2, поэтому NFEs-правильный способ сделать это в настоящее время.
вот много материала для чтения по этой теме:http://kangax.github.io/nfe/
1 присваивать его переменной не обязательно, он просто служит примером, чтобы отличить его от простого объявления функции. Это может быть любой другой контекст, где JS ожидает выражение (аргумент функции, для образец.)
2 вы получите сообщение об ошибке, если у вас есть строгого режима в действительности и попробуйте использовать arguments.callee
.
проблема
вы используете выражения с именованными фунциями - и имя выражения функции недоступно за пределами области действия этой функции:
// 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
просочиться в охватывающую область. Присвоение именованного выражения функции переменной является лишь частным случаем этого, что просто происходит с посмотреть как объявление функции.
addNums
is доступно только в области недавно определенной функции.
совершенно очевидно, когда выражение функции имеет имя (технически - Идентификатор), он называется выражения с именованными фунциями. Что ты увиденный в самом первом примере-var bar = function foo () {}; - был именно это-именованное выражение функции с foo, являющимся функцией имя. Важно помнить, что это имя только доступно в области недавно определенной функции; спецификации поручают это идентификатор не должен быть доступен для видимости.
читать более подробную форму в этой статье.
вы должны либо объявить именованную функцию:
function addNums(){
}
или назначить функцию переменной:
var add= function(){// your code }
причина, по которой addNum() ничего не возвращает, заключается в том, что он не добавляется в глобальную область с тем, как вы ее объявляете.
function addNums(a, b) {
return a+b;
}
var add = addNums;
alert("add: "+ add(2,3));
alert("addNums: "+addNums(2,3));
Я добавил ваш код в мое тестовое веб-приложение и отлично работает для меня. Вот код. Не могли бы вы поделиться более подробной информацией о своем коде/приложении?
<%@ 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>
Ура!!!
рассмотрим следующий код:
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));
Я немного изменил ваш код:
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));
и затем продолжил запускать его внутри узла.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.
addNums не является функцией в глобальном пространстве имен.. Это функция, определенная только внутри оператора присваивания..
Если вы хотите иметь доступ к нему попробовать последующих:
function addNums(a, b)
{
return a+b;
}
var add = addNums;
var add = function <---- the function name is add and it's value is a function..