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

IT技术 javascript function
2021-02-11 16:06:20

代码是这样的(语法可能看起来很奇怪,但据我所知,它没有任何问题。或者有吗?)

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

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

6个回答

您看到的是命名函数表达式 (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.

+1 用于解释使用命名函数表达式的原因和位置。
2021-03-30 16:06:20
@Tomalak 您的回答很有帮助。也谢谢你的链接:)
2021-04-05 16:06:20

问题

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

// 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() 不返回任何内容的原因是因为它没有按照您声明的方式添加到全局范围内。

@c 2 我也不认为这种声明有什么问题。
2021-03-19 16:06:20

演示

function addNums(a, b) {
   return a+b;
}
var add = addNums;
alert("add: "+ add(2,3));
alert("addNums: "+addNums(2,3));