假设我想用onClick方法调用一个函数。像这样:
<li class="inline" onclick="mve(this);" >TEMP</li>
并且我有一个JS函数,如下所示:
function mve(caller){
caller.style.position = "relative";
caller.style.left = (caller.style.left+20) +'px';
var foo = setTimeout('mve(caller)', 2000);
}
我的问题是,在初始onClick调用之后,该元素(调用者所指的元素)是不确定的。至少这是Firebug告诉我的。
我敢肯定这是一个简单的解决方案,那么对原因以及原因的简单解释又如何呢?
另外,如果我这样运行它:
function mve(caller){
caller.style.position = "relative";
caller.style.left = (caller.style.left+20) +'px';
}
我认为该元素将在每次点击时向右移动20px,但是事实并非如此。有什么想法吗?
最佳答案
setTimeout()
在全局范围内执行字符串参数,因此this
的值不再存在,参数caller
也不再存在。这是不将字符串参数与setTimeout一起使用的众多原因之一。使用这样的实际javascript函数引用,解决相应传递参数的问题很容易:
function mve(caller){
caller.style.position = "relative";
caller.style.left = (caller.style.left+20) +'px';
setTimeout(function() {
mve(caller)
}, 2000);
}
对于问题的第二部分,
caller.style.left
将像20px
那样具有单位,因此,当您向其中添加20
时,您会得到20px20
,但这并不是浏览器会理解的值,因此什么也不会发生。您将需要从中解析出实际数字,将数字添加20,然后像下面这样添加单位:function mve(caller){
caller.style.position = "relative";
caller.style.left = (parseInt(caller.style.left), 10) +20) + 'px';
setTimeout(function() {
mve(caller)
}, 2000);
}
此功能缺少的东西是它停止重复的一种方式。就像您现在拥有的那样,它会永远持续下去。我可能建议传递这样的多次迭代:
function mve(caller, iterationsRemaining){
caller.style.position = "relative";
caller.style.left = (parseInt(caller.style.left), 10) +20) + 'px';
if (--iterationsRemaining) > 0) {
setTimeout(function() {
mve(caller, iterationsRemaining)
}, 2000);
}
}
另外,您可能很想知道这并不是真正的递归函数。这是因为
mve()
函数调用setTimeout()
然后立即完成。是setTimeout()
在一段时间后执行mve()
的下一次迭代,并且在多个函数调用的堆栈帧上没有累积,因此没有实际的递归。乍一看,它的确看起来像递归,但从技术上来说并不是。