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 で文字列パラメーターを使用しない多くの理由の 1 つです。このような実際の JavaScript 関数参照を使用すると、それに応じて渡される引数を取得するのは非常に簡単な問題です。

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

質問の 2 番目の部分では、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 に答える