繁体   English   中英

Javascript 函数像“var foo = function bar() ...”?

[英]Javascript functions like "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()被声明为一个函数。 因此,当我将参数传递给它时,它也应该返回结果。

那么,为什么我没有收到第二个警报框?

您看到的是命名函数表达式 (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您将收到错误消息。

问题

您正在使用命名函数表达式- 并且函数表达式的名称在该函数的范围之外不可用:

// 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仅在新定义的函数范围内可用

很明显,当一个函数表达式有一个名字(技术上——标识符)时,它被称为命名函数表达式 你在第一个例子中看到的 - 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));

我已将您的代码添加到我的测试 Web 应用程序中,并且对我来说效果很好。 这是代码。 您能否分享您的代码/应用程序的更多详细信息?

<%@ 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));

然后继续在 node.js 中运行它以获取以下输出:

[Function: addNums]
function
add: 5

/home/mel/l.js:44
console.log("addNums: "+addNums(2,3));
                        ^
ReferenceError: addNums is not defined (... backtrace)

通常,分配了内联匿名方法的变量在使用console.log(var);调用时会打印出[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..            

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM