JavaScript 中的范围(我认为?!)挑战
Scope (I think?!) challenge in JavaScript
使用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);
}
}
发生的事情是,只有最后一颗脉冲星会发光(无论群体中有多少)。我想知道是否是因为只附加了一个事件侦听器?还是以某种方式将所有听众都添加到一个"脉冲星"中?请帮忙!
编辑:成功!感谢 Robert(以及 Bergi 对类似问题的链接),我得到了帮助,更多地了解了闭包和解绑传递给函数的变量 - 正如另一个线程上的链接所说:
"如果我们传递一个参数,函数会制作自己的本地副本 变量(如果不是通过引用传递的对象类型)"
这允许每个脉冲星有一个离散的母体参考,由myParent的每次迭代定义,而不是由myParent的最终值持有的单个外范围参考。(@Robert 科里特尼克 如果我误解或这是不正确的,请告诉我!感谢您的帮助,如果我对该网站不是那么陌生,我会 +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));
}
}
但如前所述__frame
这可能不起作用,因为它使用最后一个myParent
脉冲实例的变量。所以你可能会得到我的第一个代码更改。
- 正在全局范围中查找JavaScript函数
- 如何通过数组更新角度子范围
- 如何使用ngrepeat和双向绑定获得指令的隔离范围
- HTML范围:动态设置值属性
- "实例范围”;TypeScript类的getter/setter
- jquery日期选择器年份范围默认值
- Jpgraph:如何手动设置X轴和Y轴的范围
- 在对象数组中查找多个值的d3范围
- 动态加载angularjs并生成控制器和范围
- 如何通过谷歌应用程序脚本从谷歌文档中的位置确定命名范围
- 在Materialize Calendar中设置年份范围
- 在MVVM视图模型中处理应用程序范围的元素
- setInterval游戏循环的范围问题
- AngularJS获取范围中的选定项目
- 从指定范围创建字符数组
- ES6是否引入了一种机制来生成块范围的函数语句(而不是表达式)
- Angularjs无法将单选按钮与嵌套范围内的模型绑定
- ngDialog-弹出窗口未更新范围变量
- 如何使用D3生成特定范围内的随机颜色
- JavaScript 中的范围(我认为?!)挑战