我有一个超时,它会调用一个函数,直到完成100%的进度。然后它执行我分配给它的功能。只有给它的值是未定义的或至少是它的一部分。
我不确定代码在哪个阶段丢失了传递的值,从而使其返回undefined
但是我已经制作了一个JS小提琴,它可以让你看到它:
我的最终结果是接收正确的值然后删除给定的元素,如下所示:
function rmv_div(div_id) {
//div_id is not properly defined so cannot find the div.
document.getElementById('result').innerHTML = div_id;
var div = document.getElementById(div_id);
div.parentNode.removeChild(div);
}
答案 0 :(得分:1)
问题是i
内部使用的变量func
是在该函数范围之外创建的,并且在每次迭代时都会增加。然后,当您在结束时致电func
时,i
等于array.length
,因此array[i]
未定义。
你可以解决它在每次迭代时创建另一个你不会增加的变量:
解决方案1 :
演示: http://jsfiddle.net/qJ42h/4/ http://jsfiddle.net/qJ42h/11/
for (var i = 0; i < array.length; i++) {
var bar = document.getElementById('bar' + array[i]),
text = document.getElementById('text' + array[i]),
remove = 'wrap' + array[i],
j = i;
do_something(bar, text, function () {
rmv_div('id' + array[j]);
}, 1);
}
解决方案2
演示: http://jsfiddle.net/qJ42h/8/ http://jsfiddle.net/qJ42h/12/
for (var i = 0; i < array.length; i++) {
var bar = document.getElementById('bar' + array[i]),
text = document.getElementById('text' + array[i]),
remove = 'wrap' + array[i];
do_something(bar, text, (function(i) {
return function(){ rmv_div('id' + array[i]); }
})(i), 1);
}
答案 1 :(得分:1)
这里的问题是你没有在闭包内隔离循环变量i
。但是,通过使用对象可以更加优雅地解决这个问题。
首先,我正在介绍将封装你想要的东西的对象;它被初始化为一个bar元素和一个函数,当它被计数到100时调用。因此,我将它称为BarCounter
:
function BarCounter(element, fn)
{
this.element = element;
this.fn = fn;
this.text = element.getElementsByTagName('div')[0];
this.counter = 0;
}
这只是构造函数;它没有做任何有用的事情;它解析了text元素,它只是它在给定元素下面可以找到的第一个<div>
标记,并存储该引用供以后使用。
现在我们需要一个可以完成工作的功能;我们称之为run()
:
BarCounter.prototype.run = function()
{
var that = this;
if (this.counter < 100) {
this.text.innerHTML = this.counter++;
setTimeout(function() {
that.run();
}, 70);
} else {
this.fn(this.element);
}
}
该功能将检查计数器是否已达到100;在此之前,它将使用当前值更新文本元素,增加计数器,然后在70毫秒后再次调用自身。您可以看到如何预先保留对this
的引用,以保留稍后调用run()
函数的上下文。
完成所有操作后,它会调用完成函数,传入BarCounter
对象操作的元素。
如果您传递要移除的元素,则完成功能会更容易:
function removeDiv(element)
{
element.parentNode.removeChild(element);
}
最后一步是调整代码的其余部分:
var array = [1];
for (var i = 0; i < array.length; ++i) {
var bar = new BarCounter(
document.getElementById('bar' + array[i]),
removeDiv
);
bar.run();
}
现在很简单;它创建一个新的BarCounter
对象并调用其run()
方法。完成:))
顺便说一句,你可以选择从对象中删除元素;当然,这取决于您自己的需求。