1

假设我想使用 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,但事实并非如此。想法?

4

2 回答 2

5

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()并且多个函数调用的堆栈帧上没有累积,因此没有实际的递归。从代码上看,它确实看起来像递归,但在技术上不是。

于 2012-04-17T01:48:50.973 回答
0

第一次调用后调用者可能超出范围。您可以通过创建一个具有全局范围的变量来保留它,该变量保留调用者的值:

var globalCaller;
function onClickEvent(caller) {
    globalCaller = caller;
    mve();
}

function mve() {
    globalCaller.style.position = "relative";
    globalCaller.style.left = (caller.style.left+20) +'px';
    var foo = setTimeout('mve()', 2000);
}

不过,这真的很丑。通过传递 li 元素的 id,然后改为调用 getElementById(),您将创建更简洁的代码。或者更好的是,使用 jQuery 并改用 $("#id") 语法。

于 2012-04-17T01:52:09.593 回答