为什么函数名称在分配给变量时会消失

Why does function name disappear when assigned to a var?

本文关键字:变量 消失 分配 函数 为什么      更新时间:2023-09-26

我正试图更深入地了解Javascript的工作原理,但以下代码一直困扰着我:

function notInVar(a, b) {
    return a + b
}
var inVar = function doesThisWork(a, b) {
    return a + b
}
document.writeln('2 + 2 = ' + notInVar(2, 2));
document.writeln('3 + 3 = ' + inVar(3, 3));
document.writeln('4 + 4 = ' + doesThisWork(4, 4));

在Chrome中,前两个document.writeln按预期执行,然后我在Chrome中获得"Uncaught ReferenceError: doesThisWork is not defined"。为什么我不能调用名为doesThisWork的第二个函数?对于这个问题,第一个函数对象notInVar存储在哪里?

第二个定义被称为命名函数表达式,由于该定义的性质,您可以通过名称调用它的唯一方法是从函数体内部的调用:

var inVar = function doesThisWork(a, b) {
    return doesThisWork(a + b); // infinite recursion!
}

这可以用于在其他匿名函数中实现递归,而不必使用类似Y组合子的东西。

函数是对象。变量inVar保存一个名为doesThisWork的函数对象。

inVar.name //=> "doesThisWork"

如果函数没有名称,则它是匿名的。

要调用存储在变量中的函数,可以使用变量名(对该对象的引用)。如果您想调用同一函数内部的函数(用于递归),您可以按其名称调用它,在本例中为doesThisWork

对于这个问题,第一个函数对象notInVar存储在哪里?

function notInVar(a, b) {
    return a + b
}

相当于

var notInVar = function (a, b) {
        return a + b
}

在您的情况下,notInVar存储在全局范围中。

然后我在中得到"Uncaught ReferenceError:does ThisWork is not defined"铬

var inVar = function doesThisWork(a, b) {
    return a + b
}

类似于

var inVar = function (a, b) {
        return a + b
    }

在功能外部访问时

您不能通过doesThisWork访问该功能,但必须通过inVar 访问该功能

按照您的编写方式,doesThisWork只能在其内部使用。

函数是一个变量,变量的范围很重要。对于第二个函数,在全局作用域中,其变量名为inVar。函数名doesThisWork在其自己的作用域内,对全局作用域不可见。所以你只能使用inVar,而不能做ThisWork。

关于这件事有很多:

首先:函数的名称将是本地的,因此您只能从内部本地调用相同的函数。除非像if(doesThisWork.caller != doesThisWork) return doesThisWork(a,b);这样过滤,否则使用时可能会触发无限递归。

第二种方法是为函数指定一个名称(不要将其作为匿名函数),而是为其容器指定一个本地名称。

TL;DR=>跳转到分析以获得更清晰的想法。

值得注意的是,函数的声明方法之间的差异

内联声明:

var x = function fnName(){}; console.log(x.prototype); => fnName {} // but used locally to x
var x = function(){}; console.log(x.prototype); => Object {} // no local name, only global x

在解析时/运行时声明:

function fnName(){}; console.log(fnName.prototype); => fnName {} // global* and local name

我的分析:是这里的局部性是由于赋值造成的,因为当你在函数中声明一个函数时,这个名称将在包含函数的本地使用,而不是在函数之外,包含函数的变量也是如此,因为它包含它和它的名称。包含函数的变量仍然可以在其作用域中使用,因为它是容器函数的本地变量,容器函数是不同的作用域。

*global这里的意思是全局到函数的位置,而不是文档。因为它对于它的容器是本地的,但是对于同一容器中的其他对象是全局的。