13

我试图更深入地了解 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 按预期执行,然后我进入"Uncaught ReferenceError: doesThisWork is not defined"Chrome。为什么我不能按名称调用第二个函数doesThisWork?就此而言,第一个函数对象 notInVar 存储在哪里?

4

6 回答 6

8

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

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

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

于 2013-07-03T02:37:06.647 回答
5

函数是对象。该变量inVar包含一个名称为 的函数对象doesThisWork

inVar.name //=> "doesThisWork"

如果一个函数没有名字,它就是匿名的。

要调用存储在变量中的函数,请使用变量名(对该对象的引用)。如果你想在同一个函数中调用函数(用于递归),你可以通过它的名字来调用它,在这种情况下是doesThisWork.

于 2013-07-03T02:36:09.403 回答
4

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

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

相当于

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

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

然后我在 Chrome 中得到“Uncaught ReferenceError: doesThisWork is not defined”

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

类似于

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

当它在函数之外被访问时

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

于 2013-07-03T02:34:01.670 回答
1

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

于 2013-07-03T02:36:08.730 回答
0

函数是一个变量,变量的范围很重要。对于第二个函数,在全局范围内,它的变量名是 inVar。函数名 doesThisWork 在它自己的范围内,对全局范围是不可见的。所以你只能使用inVar,不能使用dosThisWork。

于 2013-07-03T02:40:26.120 回答
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

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

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

于 2013-07-03T04:01:12.677 回答