我得到了意想不到的结果。这是代码:
b = function c() {
console.log(c);
c = 3;
console.log(c);
}
b();
我认为第二个console.log应该打印“3”,但我自己得到了这个功能。为什么呢?
同时,从下面的代码我得到了正确的“3”。
function ff() {
ff = 3;
console.log(ff);
}
ff();
答案 0 :(得分:11)
您不能在自己的声明中覆盖函数的命名变量。 NFE(命名函数表达式)名称不能被覆盖(因为它是常量)
在严格的JS模式下编写时很明显。请尝试以下示例:
'use strict';
var b = function c(){
console.log(c);
c = 3; // c still is a function
console.log(c);
}
b();
答案 1 :(得分:8)
您使用的是function expression:
FunctionExpression:
function Identifier opt (FormalParameterList opt ){FunctionBody}
所以b = function c() { ... };
完全有效,严格模式或其他方式。 c
会发生什么问题。根据规格:
制作
FunctionExpression:function Identifier( FormalParameterList opt ){FunctionBody}
评估如下:[...]
3.调用envRec的 CreateImmutableBinding 具体方法 传递Identifier的String值作为参数 4.让闭包成为创建一个新的Function对象的结果 如13.2 [...]中所述 5.调用envRec的InitializeImmutableBinding具体方法 传递Identifier和closure的String值作为参数 [...]请注意
可以引用FunctionExpression中的标识符 在FunctionExpression的FunctionBody中允许该函数 递归地称呼自己。但是,与FunctionDeclaration不同, FunctionExpression中的标识符无法引用和执行 不影响包含FunctionExpression的范围。
所以:
c
在函数内部可见但不在其外部c
不能从函数内部覆盖(“不可变”绑定)同时,从下面的代码我得到了正确的“3”
function ff() {
这是函数声明;这里适用不同(更明显)的规则。
答案 2 :(得分:1)
第一个示例中显示的这种函数声明模式称为NFE(命名函数表达式),而另一个称为函数声明。最大的区别是,在NFE的情况下,函数的名称,i.e. c
在我们的例子中只存在于函数的范围内。因此,如果您尝试通过其名称从外部调用它,则会收到错误c is not defined
,这意味着c
在全球范围内不存在。
b = function c(){
console.log(c);
c=3;
console.log(c);
}
c(); //c is not defined
现在仔细查看 c 函数体内的c=3
行。这个代码块通常会做的是在函数体外创建一个名为c的全局变量,它也可以在函数外部访问。但是,在这里,因为c
已经存在于函数自身的范围内,所以它不会让你在那里声明,因为它意味着覆盖它自己的名字,这在 NFE ,(但在函数声明的情况下允许,即第二个问题的例子)。这正是分配代码c=3
在这里没有做任何事情的原因。
要更仔细地实现它,您可以使用c=3
更新var c=3
,在这种情况下,它会让您在函数体中以c
的名称声明一个局部变量,然后你可以在函数内部使用。
b = function c(){
console.log(c);
var c=3;
console.log(c);
}
b();