在JavaScript范围(我想?)挑战[复制](Scope (I think?!) challen

2019-10-21 16:09发布

这个问题已经在这里有一个答案:

  • JavaScript的闭包内环路-简单实用的例子 44个回答

使用CreateJS,我有输出与各种对象的实例画布,以各种方式制作动画。 几乎所有好的工作,除了一个问题,我认为这是一个范围的问题,但我不知道如何解决。 我具有由“_pulsars”,包含对象“脉冲星”的11个实例引用一个实例,代码运行是这样的:

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);
    }
}

什么情况是,只有最后的脉冲星动画(无论多少都是组)。 我不知道是否是因为只有一个事件侦听器被附? 或以某种方式所有的听众都被添加到一个“脉冲星”? 请帮忙!

编辑:成功了! 感谢罗伯特(也BERGI的链接到类似的问题),我被扶了解一点关于关闭和解除绑定变量被传递到功能 - 如其他线程上的链接说:

“如果我们通过一个参数[该]功能使变量的其自己的本地副本(如果它不反对其通过引用传递型)”

这允许每个脉冲星具有由myParent的每次迭代所限定,而不是被关由myParent的最终值的单个外范围的基准的离散参考到其父。 (@Robert Koritnik请让我知道,如果我有误解或这是不正确!感谢您的帮助,如果我不是那么新的网站我会+1。很快,希望)

Answer 1:

您遇到的问题是,你遍历你的脉冲星递增i前进的道路上,并添加这些事件侦听器。 所以,当您的一线明星其实开火,他们使用myParent (有时介意你有可能使用错字在它前面强调有时不是),这是最后一组最后脉冲星时,你的循环结束(最后的值可变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最后的变量myParent脉冲实例。 所以,你可以用我的第一个代码的改变而告终。



文章来源: Scope (I think?!) challenge in JavaScript [duplicate]