setTimeout是否创建函数实例?

时间:2015-03-18 22:30:26

标签: javascript jquery settimeout

这可能是一个菜鸟问题。以下代码就像我想要的那样,但我不知道为什么。

var x = 0

init_page = function(){
    x++;


    var y = x;

    setTimeout(go, 1000);
    function go(){
        $('body').append('<div>Y: '+y+'</div>');
    }

}
init_page();

Demo

如果您快速点击链接几次,它将打印1,2,3,4 ...

我的问题是它们都调用相同的函数,但它的作用就好像函数已经像这样实例化了:

    function go1(){
        $('body').append('<div>Y: 1</div>');
    }
    function go2(){
        $('body').append('<div>Y: 2</div>');
    }
    function go3(){
        $('body').append('<div>Y: 3</div>');
    }

他们不应该在执行时打印相同的号码(最大的号码)而不是点击时的号码吗? 我希望看到4,4,4,4,因为go()对于所有间隔都是相同的函数。

3 个答案:

答案 0 :(得分:1)

由于go包含在init_page()中,因此每次排队新的时候,它都会获得定义的函数的不同实例。其中每个变量都有自己的y变量,如init_page中所声明的那样,它将具有从当前x的当前值{{1}分配给它的值。被调用 - 这就是你看到自己行为的原因。

答案 1 :(得分:1)

您声明了一个局部变量y,它与内联函数go的范围捆绑在一起。变量y初始化为x的值 - 但由于它是基元(按值传递,而不是引用),对yx的更改不会影响每个其他

如果您将y移到init_page之外,则此行为会发生变化。

答案 2 :(得分:1)

这种技术在Javascript中称为“Closure”。当内部函数可以访问外部函数的范围并保留特定调用的外部范围时。当“go”函数由“setTimeout”执行时,这实际上发生在你的代码中 - 它保留每次调用的“init_page”函数的外部作用域状态。

关闭javascript中的一个强大功能,您可以查看以下使用它们可以实现的示例:

  1. 封装 - 使您的函数成员变为私有(只能在您的函数(对象)范围内访问)。
  2. 在循环内部处理异步调用时保留外部作用域状态。 (在你的情况下是setTimeout)
  3. 您也可以在这里找到一些详细的答案:How do JavaScript closures work?