Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/429.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么函数名在分配给变量时消失?_Javascript - Fatal编程技术网

Javascript 为什么函数名在分配给变量时消失?

Javascript 为什么函数名在分配给变量时消失?,javascript,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

我正试图深入了解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按预期执行,然后我得到
“uncaughtreferenceerror:does此工作未在Chrome中定义”
。为什么我不能调用第二个函数名为
doesthisswork
?因此,第一个函数对象notInVar存储在哪里

因此,第一个函数对象notInVar存储在哪里

相当于

var notInVar = function (a, b) {
        return a + b
}
在您的情况下,
notInVar
存储在全局范围中

然后我在中得到“uncaughtreferenceerror:doesthisswork未定义” 铬

类似于

var inVar = function (a, b) {
        return a + b
    }
在功能外部访问它时


您不能通过
doesthisswork
访问函数,但必须通过
inVar

以编写的方式访问函数,
doesthisswork
仅在其内部可用。

函数是对象。变量
inVar
包含一个名为
的函数对象,该函数对象执行此工作

inVar.name //=> "doesThisWork"
如果一个函数没有名字,它是匿名的


要调用存储在变量中的函数,可以使用变量名(对该对象的引用)。如果要在同一个函数内调用函数(对于递归),可以通过其名称调用它,在本例中,
执行此工作
第二个定义称为a,并且由于该定义的性质,只能从函数体内部通过名称调用它:

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

这可以用来在一个匿名函数中实现递归,而不必使用。

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

关于这一点,有很多方面:

第一:函数的名称将是本地的,因此您只能从本地调用相同的函数。如果(doesThisWork.caller!=doesThisWork)返回doesThisWork(a,b),则它在使用时可能会触发无限递归,除非像这样进行过滤
if(doesThisWork.caller!=doesThisWork)

第二,您正在为函数指定一个名称(不是将其作为匿名函数),而是为其容器指定一个本地名称

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

注意函数的声明方法之间的差异很有趣:

内联声明:

在分析时/运行时声明:

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


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

@stackErr:看起来不错。这是一个命名函数表达式。不确定,但我要说的是变量范围。。偶然检查一下,它在IE中“起作用”,因为IE坏了。:-)可选名称只能在函数内部使用,不能在函数外部使用。顺便说一句,ECMA参考用于,向下滚动到带有可选标识符的零件,它应该变得清晰。不太清楚。。。最接近的等价物是
var foo=function foo(){}
,这样您仍然有一个
名称可以显示在调用堆栈跟踪中。@elclanrs:我想我需要重写它。它类似于在函数外部访问它。谢谢你的指点,有什么问题吗way@KhanhTO实际上,当您从inVar访问doesThisWork时,实际上是在访问函数而不是doesThisWork,doesThisWork是包含它的变量(或对象)的局部变量,不能从外部调用。这同样适用于在另一个函数中声明的函数。这与Y组合子有什么关系?这不会让你像Y-Combinator那样做无限递归,如果你这么建议的话。@CrazyTrain Y-Combinator影响匿名递归;无限递归总是可能的:)使用Y-Combinator,您可以有无限递归,因为调用堆栈不会增长。为函数命名并不能阻止调用堆栈的增长。JavaScript函数不是尾部调用优化的。@CrazyTrain我现在明白你的意思了;它也与答案本身有点不相关,“无限递归”评论只是警告人们不要尝试代码而不知道他们在做什么:当然,我也认为递归是无限的,即使堆栈中断HEH。谢谢解释“函数名称的去向”。
var inVar = function doesThisWork(a, b) {
    return doesThisWork(a + b); // infinite recursion!
}
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