2009-08-14 9 views
4

オブジェクト配列をJavascriptのsetTimer関数に渡したいとします。ArrayオブジェクトをsetInterval関数に渡す方法

setTimer("foo(object_array)",1000); 

このコードに誤りがあります。

**注:**申し訳ありません。私の質問でいくつかの修正:setInterval()関数で可能です。

答えて

17

setTimeoutまたはsetInterval機能の最初のパラメータに文字列の代わりに無名関数を使用します。それが動作する理由

// assuming that object_array is available on this scope 
setInterval(function() { foo(object_array); }, 1000); 

は:あなたは、内側の関数を定義する場合

、それが参照することができます親機能がすでに終了した後でも、それらの変数を外部の囲み関数内に存在する変数に変更します。

この言語機能はclosuresと呼ばれます。

あなたはこれらの関数の最初の引数として文字列を渡すと、コードがeval関数の呼び出しを使用して、内部で実行され、これを行うことはgood practiceとして考えないなっております。

評価もevalのを使用して、JavaScriptのコンパイラへの直接アクセスを提供し、それは、発信者の権限で渡されたコードを実行し、繰り返し/広範囲(すなわち、あなたのsetInterval関数が良い例です)パフォーマンスの問題につながります。

+0

それは(のsetIntervalで可能です) – coderex

+0

はい、それはpossbleだとそれはそれを – CMS

+0

@CMSを行うための最善の方法です:それはトラップのバージョン – coderex

1

最初は、それはsetTimeoutを「

秒だが、文字列を渡すことはありません。実際の解決策は、残りのコードに依存します。最も堅牢な方法は、スコープをトラップすることです。

var obj_array = something; 
function trap(obj) 
{ 
    function exec() { foo(obj); } 
    return exec; 
} 
setTimeout(trap(obj_array), 1000); 

トラップは、スコープ内にトラップされた配列を持つ関数を返します。これはあなたの問題にそれが特定の作るためしかし、一般的な機能である、それを簡略化することができます。

var obj_array = something; 
function trap() 
{ 
    function exec() { foo(obj_array); } 
    return exec; 
} 
setTimeout(trap(), 1000); 

かさえ:

var obj_array = something; 
function trap() 
{ 
    foo(obj_array); 
} 
setTimeout(trap, 1000); 

そして最後まで凝縮:

var obj_array = something; 
setTimeout(function() { foo(object_array); }, 1000); 

EDIT : 私の機能(またはここでバックアップで見つけたそれらの1回以上の反復)

Function.prototype.createDelegate = function(inst, args) { 
    var me = this; 
    var delegate = function() { me.apply(inst, arguments); } 
    return args ? delegate.createAutoDelegate.apply(delegate,args) : delegate; 
}; 
Function.prototype.createAutoDelegate = function() { 
    var args = arguments; 
var me = this; 
return function() { me.apply({}, args); } 
}; 

は、与えられた:

function test(a, b) { alert(a + b); } 

USAGE:

setTimeout(test.createAutoDelegate(1, 2), 1000); 

または指定された:

var o = { a:1, go : function(b) { alert(b + this.a); }} 

USAGE:

setTimeout(o.go.createDelegate(o,[5]), 1000); 
//or 
setTimeout(o.go.createDelegate(o).createAutoDelegate(5), 1000); 
2

を私はEXPANに行きますよこれは、CMSの(そしてこの種の質問に対するほとんどの答え)がそうではないというユースケースに対応しているからです。

あなたはタイムアウトを設定した時刻に関数呼び出しにあなたの引数をバインドする必要がある場合は、簡単な関数エンクロージャは動作しません:あなたは、上記の意志をFirebugののコンソールを使用していると仮定すると、

echo = function (txt) { console.log(txt); }; 

val = "immediate A"; 
echo(val); 

val = "delayed"; 
window.setTimeout(function() { echo(val); }, 1000); 

val = "immediate B"; 
echo(val); 

1秒後に「即時A」、「即時B」、「即時B」を出力します。 setTimeoutコール時に値をバインドするには、Lukeのトラップメソッドを使用します。以下は、それは少し任意の関数と引数の長さを受け入れるように変更しますが、暗黙的に呼び出し元のコンテキストを渡す方法ですが、さらに「この場合はcontext引数を受け入れるように拡張することができれば

echo = function (txt) { console.log(txt); }; 

trap = function (fn, args) { 
    return function() { 
     return fn.apply(this, args); 
    }; 
}; 

val = "immediate A"; 
echo(val); 

val = "delayed"; 
window.setTimeout(trap(echo, [val]), 1000); 

val = "immediate B"; 
echo(val); 

わかりません"あなたをそこに連れてこない。

+0

:-)おかげで働いている私のcreateDelegateとtrapScope機能に同じ考えです。関心のある答えの一番下に追加 –

+0

私は過去にこの問題を数回処理していましたが、あなたの解決策を見いだすまで、厄介な状態を追跡するための解決策をいつも決めました。タイムアウトとインターバルについてわかったすべてのトピックは、競合状態を考慮せずにエンクロージャを使用することについて話しました。 –

+0

'+ 1'この答えは私の額が壁に当たるのを助けました。ありがとう。 – RASG

関連する問題