我猜这是某种“范围”问题,但我想理解为什么会这样。
function foo(){
return true;
}
function bar(){
var foo = foo();
console.log(foo);
}
var foo = foo();
console.log(foo); //returns true as expected
但是,当我做以下
时
function foo(){
return true;
}
function bar(){
var foo = foo();
console.log(foo);
}
bar(); //returns Uncaught TypeError: foo is not a function
似乎变量名称不能与函数名称相同。但这不是真的吗?
答案 0 :(得分:4)
有两个概念可以帮助您理解这一点:
第一个是阴影,这意味着如果在范围内定义变量名称,它将隐藏父范围内的相同变量名称(或函数名称)。
第二个是提升,这会导致任何变量声明移动到本地范围的顶部。
此代码
function foo(){}
function bar(){
var foo = foo();
console.log(foo);
}
等同于此
var foo;//will initialize foo to undefined
foo = function(){}
var bar;
bar = function(){
var foo;//will shadow parent foo and initialize foo to undefined
foo = foo(); //fails because you are trying to call an undefined object
console.log(foo);
}
希望,这很明显为什么'foo不是一个函数'。你的bar函数声明了一个新的foo变量(隐藏了bar范围内的全局变量),然后通过调用自身来尝试分配这个变量。
您可以在此处详细了解var
的错综复杂信息:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/var
答案 1 :(得分:1)
在JavaScript中,函数声明(如foo
声明)创建的名称与变量非常相似。因此,您的第二个示例失败的原因与此示例警告2而不是1:
var a = 1;
function bar() {
var a = 2;
alert(a);
}
...因为a
阴影内的bar
a
以外的bar
bar
自bar
以来一直在范围内关闭它。
似乎变量名称不能与函数名称相同。但这不是真的吗?
变量名称确实可以与函数名称相同,但如果您在嵌套作用域中执行此操作(如您所愿),则变量名称 shadow 函数名称。
在function bar(){
var foo = foo();
console.log(foo);
}
:
foo
... foo()
中的bar
是undefined
中声明的变量,而不是外部作用域中声明的函数。因此,它具有默认值变量(var foo
),无法调用,因此您会收到错误。
在评论中你问过:
因为我在第二个例子中覆盖了foo,所以我不是在第一个例子中覆盖它吗?
不,这将我们带回到上面的第一个语句:函数声明创建的名称非常类似于变量。因此,如果声明一个函数,然后稍后声明一个具有相同名称的变量,则忽略变量声明。因此,您的第一个示例被解释为在全局范围内根本没有var foo = foo();
。所以foo = foo()
真的是foo
,它运行得很好,调用foo
然后使用返回值来更新{{1}}。 (再次执行会失败,因为函数返回的值不可调用。)
答案 2 :(得分:0)
检查代码上的推荐
function foo(){
return true;
}
function bar(){
var foo = foo(); // before calling foo(), foo is defined as a variable, so foo is not a function anymore in this scope.
console.log(foo);
}
bar(); //returns Uncaught TypeError: foo is not a function