无法从函数内部覆盖函数

时间:2017-12-22 07:12:56

标签: javascript function scope

我得到了意想不到的结果。这是代码:

b = function c() {
  console.log(c);
  c = 3;
  console.log(c);
}
b();

我认为第二个console.log应该打印“3”,但我自己得到了这个功能。为什么呢?

同时,从下面的代码我得到了正确的“3”。

function ff() {
  ff = 3;
  console.log(ff);
}
ff();

3 个答案:

答案 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();