Javascript将参数传递给循环内的setTimeout函数
我试图在Javascript中的for循环内执行setTimeout()函数,但我得到了错误“shape未定义”,即使它已定义,我将其作为setTimeout()调用中函数的参数传递。如果我删除setTimeout存储模块,该函数就可以正常工作 为什么我会出现这个错误?我如何修复它 谢谢Javascript将参数传递给循环内的setTimeout函数,javascript,loops,Javascript,Loops,我试图在Javascript中的for循环内执行setTimeout()函数,但我得到了错误“shape未定义”,即使它已定义,我将其作为setTimeout()调用中函数的参数传递。如果我删除setTimeout存储模块,该函数就可以正常工作 为什么我会出现这个错误?我如何修复它 谢谢 function fadeShapes(layer, movement, opacity, speed) { var shapes = layer.getChildren(); for(var
function fadeShapes(layer, movement, opacity, speed) {
var shapes = layer.getChildren();
for(var n = 0; n < shapes.length; n++) {
var shape = layer.getChildren()[n];
setTimeout(function(shape){
shape.transitionTo({
alpha: opacity,
duration: speed
});
}, 100);
}
}
功能Fadeshape(图层、移动、不透明度、速度){
var shapes=layer.getChildren();
对于(var n=0;n
这是一个常见的关闭问题,下面是固定代码:
function fadeShapes(layer, movement, opacity, speed) {
var shapes = layer.getChildren();
for(var n = 0; n < shapes.length; n++) {
var shape = layer.getChildren()[n];
setTimeout((function (bound_shape) {
return function() { // return function!
bound_shape.transitionTo({
alpha: opacity,
duration: speed
});
};
}(shape)) // immediate execution and binding
, 100);
}
}
功能Fadeshape(图层、移动、不透明度、速度){
var shapes=layer.getChildren();
对于(var n=0;n
代码中发生的情况是,for循环将运行,n
函数将在100ms
中从执行开始调度,但是shape
的值会更改!因此,当调用回调时,shape
是shapes[length-1]
(最后一个形状)的值
要修复它,必须使用闭包“关闭”该值。在这种情况下,绑定
shape
值并返回要在100ms
JavaScript中执行的函数的函数没有块作用域,因此所有超时函数都指向同一个变量shape
,循环完成后该变量指向数组的未定义索引。您可以使用匿名函数来模拟要查找的范围:
for(var n = 0; n < shapes.length; n++) {
var shape = shapes[n]; //Use shapes so you aren't invoking the function over and over
setTimeout((function(s){
return function() { //rename shape to s in the new scope.
s.transitionTo({
alpha: opacity,
duration: speed
});
};
})(shape), 100);
}
forEach
内置于现代浏览器中,但可以在Internet Explorer的旧浏览器中进行填充。以下是迭代器的代码,它考虑了100ms
延迟。(未经测试)
函数迭代(数组、超时、回调){
var n=0,length=array.length;
函数步骤(){
回调(数组[n]);
n+=1;
如果(n*/、不透明度、速度){
var shapes=layer.getChildren();
迭代(形状,100,函数(形状){
形转换({
α:不透明度,
持续时间:速度
});
});
}
请注意,通过以这种方式使用
iterate
函数,也可以解决闭包问题。如果希望setTimeout调用间隔100毫秒执行,则只需在每个set Timeout调用中添加100毫秒:
function fadeShapes(layer, movement, opacity, speed) {
var shapes = layer.getChildren();
for(var n = 0; n < shapes.length; n++) {
var shape = shapes[n];
setTimeout((function(local_shape){
return function(){
local_shape.transitionTo({
alpha: opacity,
duration: speed
});
}
})(shape), 100 + n*100);
}
}
功能Fadeshape(图层、移动、不透明度、速度){
var shapes=layer.getChildren();
对于(var n=0;n
试试:
功能Fadeshape(图层、移动、不透明度、速度){
var shapes=layer.getChildren();
对于(var n=0;n
请注意,所有setTimeout调用都将设置为在100毫秒延迟后同时运行(给或拿一两毫秒),它们不会间隔100毫秒运行。你明白我的意思了吧,罗伯!如何实现您描述的功能?@j-man86我已经添加了一个详细说明解决方案的答案。@j-man86-您可以按照Greg的建议使用递增计数器在循环中设置它们,或者您可以让每一个调用下一个,直到达到某个限制。+1
使用“块范围”<代码>变量形状实际上被“提升”到函数的开头,在最初的问题中,循环结束后,shape
指向什么并不重要,因为当超时函数触发时,shape
完全超出范围。@kojiro:JavaScript中的作用域不是这样的。函数永远不会失去它原来的作用域。JavaScript函数是闭包,这意味着无论在何处调用它们,它们都会携带其原始作用域。@amnotiam yes,并且带有值的shape
与传递给setTimeout
@kojiro:Right的函数参数shape
不同。该参数未定义。它需要将值传递给它,或者将其删除,这将给我们留下fadeShapes
函数范围中的shape
。。。您认为哪一种效率更高?就性能而言,setInterval
和setTimeout
之间没有太大区别<如果由于调用堆栈上的限制而迭代大量元素,setTimeout
可能会出现问题,setInterval
不存在此问题。只要确保完成后清除计时器(clearInterval
)
function iterate(array, timeout, callback) {
var n = 0, length = array.length;
function step() {
callback(array[n]);
n += 1;
if (n < length) { // are there more elements?
setTimeout(step, timeout);
}
}
setTimeout(step, timeout); // start
}
function fadeShapes(layer, movement /* unused> */, opacity, speed) {
var shapes = layer.getChildren();
iterate(shapes, 100, function (shape) {
shape.transitionTo({
alpha: opacity,
duration: speed
});
});
}
function fadeShapes(layer, movement, opacity, speed) {
var shapes = layer.getChildren();
for(var n = 0; n < shapes.length; n++) {
var shape = shapes[n];
setTimeout((function(local_shape){
return function(){
local_shape.transitionTo({
alpha: opacity,
duration: speed
});
}
})(shape), 100 + n*100);
}
}
function fadeShapes(layer, movement, opacity, speed) {
var shapes = layer.getChildren();
for(var n = 0; n < shapes.length; n++) {
var shape = layer.getChildren()[n];
(function(sh) {
setTimeout(function(){
sh.transitionTo({
alpha: opacity,
duration: speed
});
}, 100);
})(shape);
}
}