为什么在分配给var时函数名称会消失?

时间:2013-07-03 02:31:11

标签: javascript

我正在努力深入了解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.writelns按预期执行,然后我在Chrome中获得"Uncaught ReferenceError: doesThisWork is not defined"。为什么我不能通过名称doesThisWork调用第二个函数?就此而言,第一个函数对象notInVar存储在哪里?

6 个答案:

答案 0 :(得分:8)

第二个定义称为named function expression,由于该定义的性质,您可以通过名称调用它的唯一方法是 inside 函数体:

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

这可用于在其他匿名函数内实现递归,而不必使用Y-combinator之类的东西。

答案 1 :(得分:5)

功能是对象。变量inVar包含名称为doesThisWork的函数对象。

inVar.name //=> "doesThisWork"

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

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

答案 2 :(得分:4)

  

就此而言,第一个函数对象notInVar存储在哪里?

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

相当于

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

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

  

然后我得到“Uncaught ReferenceError:doesThisWork is not defined”in   铬

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

类似于

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

当访问外部功能

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

访问该功能

答案 3 :(得分:1)

您编写的方式,doesThisWork仅在其内部可用。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

这有很多事情:

首先:该函数的名称将是本地的,因此您只能在本地调用相同的函数。这可能会在使用时触发无限递归,除非它像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

我的分析:是这里的位置是由于在函数中声明函数时的赋值,该名称将在本地用于包含函数,而不是在包含函数之外,同样如此对于包含函数的变量,因为它包含它和它的名称。仍然包含该函数的变量可以在其范围内使用,因为它是容器函数的本地变量,它是一个不同的范围。

* 全局此处表示函数位置的全局,而不是文档。因为它是它的容器的本地,但是对同一容器中的其他对象是全局的。