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

JavaScript中的范围(我认为是?!)挑战,javascript,scope,Javascript,Scope,使用CreateJS,我输出了一个画布,其中包含各种对象的实例,并以各种方式设置动画。除了一个问题,我认为这是一个范围问题,但我不知道如何解决,几乎所有的工作都正常。我有一个由“_pulsar”引用的实例,其中包含11个对象“pulsar”的实例,代码运行如下: function attachPulseFuncs() { var defaultFreq = 0.05; // controls the likelihood of a 'pulse' happening for

使用CreateJS,我输出了一个画布,其中包含各种对象的实例,并以各种方式设置动画。除了一个问题,我认为这是一个范围问题,但我不知道如何解决,几乎所有的工作都正常。我有一个由“_pulsar”引用的实例,其中包含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);
    }
}
函数attachPulseFuncs(){
var defaultFreq=0.05;//控制“脉冲”发生的可能性
对于(var i=0;i<_pulsars.children.length;i++){
var myParent=_pulsars.children[i];
myParent.isPulsing=false;
_myParent.pulse=函数(){
if(myParent.isPulsing==false){
myParent.isPulsing=true;
myParent.\uuu帧=1
var tween=createjs.tween.get(myParent.to({uuu frame:65},1500).call(myParent.resetPulse);
tween.addEventListener(“更改”,函数(){
myParent.gotoAndStop(myParent.\uu帧);
});
}
}
myParent.resetPulse=函数(){
myParent.gotoAndStop(1);
myParent.isPulsing=false;
}
myParent.callRandomPulse=函数(){
var ran=Math.random();
if(ran
发生的情况是,只有最后一颗脉冲星(无论组中有多少个脉冲星)会产生动画。我想知道这是否是因为只连接了一个事件侦听器?或者所有的听众都被添加到一个“脉冲星”?请帮忙

编辑:成功 感谢Robert(以及Bergi与类似问题的链接),我对闭包和解除绑定传递到函数中的变量有了更多的了解,正如另一个线程上的链接所说:

“如果我们传递一个参数,[the]函数将生成它自己的 变量(如果不是通过引用传递的对象类型)


这使得每个脉冲星都有一个由myParent的每次迭代定义的对其父星的离散参考,而不是由myParent的最终值保持的单个外部范围参考。(@Robert Koritnik如果我有误解或这是不正确的,请告诉我!谢谢你的帮助,如果我不是这个网站的新手,我会+1。希望很快会这样做)

你遇到的问题是,你在一路上迭代你的脉冲星递增
I
,并添加那些事件侦听器。因此,当您的列表器实际启动时,它们会使用
myParent
(注意您可能的输入错误,有时在其前面使用下划线,有时不使用下划线)变量,该变量上次设置为for循环完成时的最后一个脉冲星(最后一个
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));
    }
}

但如前所述,这可能不起作用,因为它使用最后一个
myParent
pulse实例的
\uu frame
变量。因此,您可能会看到我的第一个代码更改。

我输入了相同的代码,但在发布并意识到两个答案都是重复的之后被删除。啊,好吧-所以我需要为每个脉冲星创建一个离散的“父”变量?我尝试创建一个变量数组(例如“myParent[I]”),但遇到了相同的问题(我想是因为“myParent[I]”在当前代码中与“myParent”相同)。谢谢你指出这一点,我该怎么解决呢?@OllySkinner:我花了一段时间才完成我的回答,但我想先给你一个提示并提供一个答案,然后再编辑它,给你所有的细节来解决它。谢谢Robert!我想我明白了,尽管范围问题适用于该函数(“pulse”),但我应该对其他函数进行类似的调整,特别是我在底部添加的createjs.Ticker事件侦听器?(在变量输入错误上也有很好的表现——实际上,这只是因为我清理了代码,试图使其更易于阅读,删除了所有控制台日志跟踪和额外的变量定义!再次感谢)。@OllySkinner:是的。正如我在回答中提到的,您应该更好地了解哪些部分似乎需要捕获变量。这是你正确发现自己的另一个原因。显然,我回答的主要目的已经实现了:让你明白为什么它不起作用。