JavaScript中的范围(我认为是?!)挑战
使用CreateJS,我输出了一个画布,其中包含各种对象的实例,并以各种方式设置动画。除了一个问题,我认为这是一个范围问题,但我不知道如何解决,几乎所有的工作都正常。我有一个由“_pulsar”引用的实例,其中包含11个对象“pulsar”的实例,代码运行如下:JavaScript中的范围(我认为是?!)挑战,javascript,scope,Javascript,Scope,使用CreateJS,我输出了一个画布,其中包含各种对象的实例,并以各种方式设置动画。除了一个问题,我认为这是一个范围问题,但我不知道如何解决,几乎所有的工作都正常。我有一个由“_pulsar”引用的实例,其中包含11个对象“pulsar”的实例,代码运行如下: function attachPulseFuncs() { var defaultFreq = 0.05; // controls the likelihood of a 'pulse' happening for
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:是的。正如我在回答中提到的,您应该更好地了解哪些部分似乎需要捕获变量。这是你正确发现自己的另一个原因。显然,我回答的主要目的已经实现了:让你明白为什么它不起作用。