为什么我的JavaScript函数名称冲突?
我只写了下面的脚本来看看当一个variables和一个函数分配给它的函数的名字冲突时会发生什么:
var f = function() { console.log("Me original."); } function f() { console.log("Me duplicate."); } f();
我得到的输出是“我原来的”。 为什么另一个函数不被调用?
另外,如果我改变我原来的赋值为var f = new function() {
,我得到“我原来的”,后面跟着一个TypeError说object is not a function
。 有人可以解释吗?
函数声明在JavaScript中被提升(移动到顶部)。 虽然在parsing顺序方面不正确,但由于函数声明是悬而未决的,因此您的代码在语义上与以下内容相同:
function f() { console.log("Me duplicate."); } var f = function() { console.log("Me original."); } f();
反过来,除了函数的名字是一样的:
var f = function() { console.log("Me duplicate."); } var f = function() { console.log("Me original."); } f();
而由于variables提升又是这样的:
var f; f = function() { console.log("Me duplicate."); } f = function() { console.log("Me original."); } f();
这解释了你所得到的,你重写了这个函数。 更一般地说,在JavaScript中允许多个var
声明 – var x = 3; var x = 5
var x = 3; var x = 5
是完全合法的。 在新的ECMAScript 6标准中, let
声明禁止这个。
这篇由@kangax撰写的文章在javascript中揭开了function的神秘面纱
如果看起来没有人回答你的后续问题,所以我会在这里回答,尽pipe你通常应该提出后续问题作为单独的问题。
你问为什么这样:
var f = new function() { console.log("Me original."); } function f() { console.log("Me duplicate."); } f();
打印出“我原来的”。 然后出错。
这里发生的事情是, new
的函数将被用作构造函数。 所以这相当于以下内容:
function myConstructor() { console.log("Me original."); } var f = new myConstructor(); function f() { console.log("Me duplicate."); } f();
由于本杰明解释的function提升,以上基本相当于:
var myConstructor = function() { console.log("Me original."); }; var f = function() { console.log("Me duplicate."); }; f = new myConstructor(); f();
这个expression式:
var f = new function() { console.log("Me original."); }
导致一个新的对象被构造并赋值给f
,使用匿名函数作为构造函数。 “我原来的。” 在构造函数执行时被打印出来。 但是构造的对象本身并不是一个函数,所以当它最终执行时:
f();
你会得到一个错误,因为f
不是一个函数。
原谅我,如果这是错误的方法来添加一个点。 我一直没有到这里来,并会欢迎build设性的方向和/或批评。
本杰明的回答非常好地解决了OP的问题,但是我想补充一点,可以让我们全面地了解这个问题以及它的古怪之处。
如果我们通过调用f
来启动原始代码,如下所示:
f(); var f = function() { console.log("Me original."); }; function f() { console.log("Me duplicate."); } f();
输出将是:
Me duplicate. Me original.
原因是var
和function
声明略有不同。
对于var
声明移动到当前作用域*的顶部,但是任何赋值都不会被挂起。 至于声明的var的值,直到达到原来的赋值行才定义。
对于function
语句 ,声明和定义都被挂起。 在var f = function() {...
构造中使用的函数expression式不会被挂起。
所以在提出之后,执行就好像代码是:
var f; // declares var f, but does not assign it. // name and define function f, shadowing the variable function f() { console.log("Me duplicate."); } // call the currently defined function f f(); // assigns the result of a function expression to the var f, // which shadows the hoisted function definition once past this point lexically f = function() { console.log("Me original."); } // calls the function referenced by the var f f();
*所有的JavaScript作用域都是词法,或者是函数,范围,但是似乎只是混淆了那些使用f这个词的东西。