JavaScript中的范围(我认为?!)挑战

时间:2015-01-23 11:12:34

标签: javascript scope

使用CreateJS,我输出了一个包含各种对象实例的画布,以各种方式进行动画制作。几乎所有工作都正常,除了一个问题,我认为是一个范围问题,但我不确定如何修复。我有一个由' _pulsars'引用的实例,包含11个对象的实例' pulsar',代码运行如下:

function attachPulseFuncs() {

    var defaultFreq = 0.05; // controls the likelihood of a 'pulse' happening

    for (var i = 0; i < _pulsars.children.length; i++) {

        var myParent = _pulsars.children[i];

        myParent.isPulsing = false;

        _myParent.pulse = function() {
            if (myParent.isPulsing == false) {
                myParent.isPulsing = true;
                myParent.__frame = 1
                var tween = createjs.Tween.get(myParent).to({__frame:65}, 1500).call(myParent.resetPulse);
                tween.addEventListener("change", function() {
                myParent.gotoAndStop(myParent.__frame);
                });
            }
        }

        myParent.resetPulse = function() {
            myParent.gotoAndStop(1);
            myParent.isPulsing = false;
        }

        myParent.callRandomPulse = function() {
            var ran = Math.random();

            if (ran < freqNumber) {
                myParent.pulse();
            }
        }

        createjs.Ticker.addEventListener("tick", myParent.callRandomPulse);
    }
}

只会发生最后一个脉冲星的动画(无论群组中有多少个)。我想知道它是否因为只附加了一个事件监听器?或者不知何故,所有的听众都被添加到了一个“脉冲星”中?请帮忙!

编辑:成功! 感谢Robert(以及Bergi与类似问题的链接),我帮助理解了关于闭包和解除传递给函数的变量的更多信息 - 正如另一个线程上的链接所说:

  

&#34;如果我们传递参数[该]函数使其自己的本地副本   变量(如果它不是通过引用传递的对象类型)&#34;

这允许每个脉冲星对 myParent 的每次迭代所定义的其父脉冲具有离散参考,而不是由的最终值保持的单个外部参考范围参考。 myParent 。 ( @Robert Koritnik 如果我误解了或者这是不正确的,请告诉我!感谢您的帮助,如果我对该网站不那么新,我会+1。很快,希望如此)

1 个答案:

答案 0 :(得分:1)

您遇到的问题是,您沿着增加i的脉冲星进行迭代并添加这些事件侦听器。因此,当你的长子实际开火时,他们会使用myParent(注意你可能的错字,有时使用前面的下划线,有时候不使用)变量,当你的for循环完成时,最后设置为最后一个脉冲星的变量(最后一个值为{{ 1}});

您必须更改此段代码

i

到此:

myParent.pulse = function() {
    if (myParent.isPulsing == false) {
        myParent.isPulsing = true;
        myParent.__frame = 1
        var tween = createjs.Tween.get(myParent).to({__frame:65}, 1500).call(myParent.resetPulse);
        tween.addEventListener("change", function() {
            myParent.gotoAndStop(myParent.__frame);
        });
    }
}

这个更改是什么创建了一个新的函数作用域,捕获myParent.pulse = (function(parent) { return function() { if (parent.isPulsing === false) { parent.isPulsing = true; parent.__frame = 1 var tween = createjs.Tween.get(parent).to({__frame:65}, 1500).call(parent.resetPulse); tween.addEventListener("change", function() { parent.gotoAndStop(parent.__frame); }); } }; })(myParent); 的当前值并将其存储在局部变量(参数)myParent中,然后返回一个使用此新捕获值的函数。

也许我已经捕获了太多,我应该只为parent函数调用创建一个新的函数范围。您应该知道哪个部分需要捕获。我的代码捕获的代码多于可能需要的代码,因此它应该也可以正常工作,但是一段时间后,当您回到它引入一些更改时,它可能会让人感到困惑。

因此,将范围缩小到最小的语句集,如:

tween.addEventListener

但如上所述,这可能无效,因为它使用了最后myParent.pulse = function() { if (myParent.isPulsing == false) { myParent.isPulsing = true; myParent.__frame = 1 var tween = createjs.Tween .get(myParent) .to({__frame:65}, 1500) .call(myParent.resetPulse); tween.addEventListener("change", (function(parent) { return function() { parent.gotoAndStop(parent.__frame); }; })(myParent)); } } 个脉冲实例的__frame变量。所以你最终可能会改变我的代码。