JavaScript 范围(我认为?!)挑战
Scope (I think?!) challenge in JavaScript
使用 CreateJS,我输出了一个 canvas,其中包含各种对象的实例,以各种方式进行动画处理。几乎所有工作正常,除了一个问题,我 认为 是一个范围问题,但我不确定如何解决。我有一个由“_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);
}
}
发生的情况是只有最后一个脉冲星有动画(无论组中有多少)。我想知道是不是因为只附加了一个事件侦听器?或者以某种方式将所有听众添加到一个 'pulsar'?请帮忙!
编辑:成功!
感谢 Robert(以及 Bergi 对类似问题的 link),帮助我更多地了解了闭包和解除绑定传递给函数的变量 - 正如另一个线程上的 link 所说:
"if we pass a parameter [the] function makes its own local copy of the
variable (if it is not object type which pass by reference)"
这允许每个脉冲星对其父级有一个离散的引用,由 myParent 的每次迭代定义,而不是最终持有的单个外部范围引用myParent 的值。 (@Robert Koritnik 如果我误解了或者这是不正确的,请告诉我!谢谢你的帮助,如果我不是这个网站的新手,我会+1。希望很快)
您遇到的问题是,您迭代脉冲星并沿途递增 i
并添加这些事件侦听器。所以当你的 listers 真的开火时,他们使用 myParent
(注意你可能的拼写错误,有时在它前面使用下划线,有时不使用)变量,当你的 for 循环完成时,它最后设置为最后一个脉冲星([= 的最后一个值13=]);
您必须更改这段代码
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
脉冲实例的 __frame
变量。所以你可能会得到我的第一个代码更改。
使用 CreateJS,我输出了一个 canvas,其中包含各种对象的实例,以各种方式进行动画处理。几乎所有工作正常,除了一个问题,我 认为 是一个范围问题,但我不确定如何解决。我有一个由“_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);
}
}
发生的情况是只有最后一个脉冲星有动画(无论组中有多少)。我想知道是不是因为只附加了一个事件侦听器?或者以某种方式将所有听众添加到一个 'pulsar'?请帮忙!
编辑:成功! 感谢 Robert(以及 Bergi 对类似问题的 link),帮助我更多地了解了闭包和解除绑定传递给函数的变量 - 正如另一个线程上的 link 所说:
"if we pass a parameter [the] function makes its own local copy of the variable (if it is not object type which pass by reference)"
这允许每个脉冲星对其父级有一个离散的引用,由 myParent 的每次迭代定义,而不是最终持有的单个外部范围引用myParent 的值。 (@Robert Koritnik 如果我误解了或者这是不正确的,请告诉我!谢谢你的帮助,如果我不是这个网站的新手,我会+1。希望很快)
您遇到的问题是,您迭代脉冲星并沿途递增 i
并添加这些事件侦听器。所以当你的 listers 真的开火时,他们使用 myParent
(注意你可能的拼写错误,有时在它前面使用下划线,有时不使用)变量,当你的 for 循环完成时,它最后设置为最后一个脉冲星([= 的最后一个值13=]);
您必须更改这段代码
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
脉冲实例的 __frame
变量。所以你可能会得到我的第一个代码更改。