7

在 Stoyan Stefanov 的“JavaScript 模式”一书中,有一部分是关于自定义函数的。

var scareMe = function(){
    console.log("Boo!");
    scareMe = function(){
        console.log("Double Boo!"); 
    }
}

scareMe();//==>Boo!
scareMe();//==>Double Boo!

它按我的预期工作。但是我修改了scareMe函数如下:

function scareMe(){
     console.log("Boo!");
     function scareMe(){
         console.log("Double Boo!");
     }
 }

 scareMe();//==>Boo!
 scareMe();//==>Boo!

问题

  1. 他们之间有什么区别?
  2. 在第二种情况下,为什么输出不是“Double Boo!”,而是“Boo!”
4

3 回答 3

11

调用的第一个scareMe函数通过scareMe在其中创建另一个函数来覆盖其自己的行为,该函数会覆盖上层范围内的函数,因此原始scareMe更改的定义,如果您想第一次设置,我已经看到使用了这种方法一个应用程序,并希望在设置后立即更改其行为。

如果您已经定义:

var scareMe = function(){
    console.log("Boo!");
    var scareMe = function(){ //define it with var
        console.log("Double boo!"); 
    }
}

scareMe();//==>Boo!
scareMe();//==>Boo! //you will see the behavior as that of the second one.

也是一次性设置的一种实际实现:

var scareMe = function(){
    console.log("Boo!");

   //I have done my job now. I am no longer needed.
    scareMe = undefined;

}

scareMe();//==>Boo!
scareMe();//==> oops error

第二种情况,您正在创建一个新函数,其名称scareMe的范围仅在函数内,它不会覆盖自身。

试试这个,例如:

function scareMe(){
     console.log("Boo!");
     function scareMe(){
         console.log("Double bool!");
     }
    scareMe(); //Now this invokes the once defined inside the scope of this function itself.
 }

 scareMe();//==>Boo! and Double bool!
于 2013-09-30T02:00:42.413 回答
4

在您的第一个方法中,scareMe 是一个全局变量(在您的上下文中)。在“双嘘”中,您更改了该全局变量的值,因此它可以工作。在第二种方法中,内部的 scareMe 是一个局部变量,它不会改变全局变量的值。所以这是关于变量范围的。

于 2013-09-30T02:03:45.540 回答
2

除了可吊装和可调试性外,还可以考虑:

function f(/* ... */) { /* ... */ }

相当于:

var f = function(/* ... */) { /* ... */ };

如果我们翻译您的第二个代码示例以使用第二种形式,我们会得到:

var scareMe = function() {
    console.log("Boo!");
    var scareMe = function() {
        console.log("Double bool!");
    };
};

请注意,这您的第一个片段不同;内部函数定义上有一个var。使用内部var,它创建了一个变量,称为scareMe阴影外部变量。

于 2013-09-30T02:02:07.237 回答