948

次のような JavaScript コードがあります。

function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)",4000);
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}

定義されていないエラーが表示されます関数topicIdを使用する前はすべてがsetTimeout()機能していました。

しばらくしてpostinsql(topicId)関数が呼び出されるようにします。私は何をすべきか?

4

29 に答える 29

1243
setTimeout(function() {
    postinsql(topicId);
}, 4000)

文字列ではなくパラメーターとして匿名関数をフィードする必要があります。後者の方法は、ECMAScript 仕様に従って機能することすらありませんが、ブラウザーは寛大です。setTimeout()これは適切な解決策です。 orを使用するときに文字列を「関数」として渡すことに依存しないでくださいsetInterval()。評価する必要があり、正しくないため遅くなります。

アップデート:

Hobblinが質問に対するコメントで述べたように、 setTimeout を使用して引数を関数に渡すことができるようになりましたFunction.prototype.bind()

例:

setTimeout(postinsql.bind(null, topicId), 4000);
于 2009-07-27T21:15:26.263 に答える
842

最新のブラウザー (つまり、IE11 以降) では、「setTimeout」は、タイマーの最後に内部関数にパラメーターとして送信される 3 番目のパラメーターを受け取ります。

例:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

詳細:

于 2011-09-21T17:23:04.260 に答える
181

いくつかの調査とテストを行った後、唯一の正しい実装は次のとおりです。

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

setTimeout はすべての追加パラメーターを関数に渡し、そこで処理できるようにします。

匿名関数は非常に基本的なものに対して機能しますが、「this」を使用する必要があるオブジェクトのインスタンス内では、それを機能させる方法はありません。無名関数は「this」をウィンドウを指すように変更するため、オブジェクト参照が失われます。

于 2012-10-30T22:08:46.347 に答える
47

これは非常に古い質問で、すでに「正しい」答えがありますが、ここでは誰も言及していない別のアプローチについて言及したいと思いました。これは、優れたアンダースコアライブラリからコピーして貼り付けたものです。

_.delay = function(func, wait) {
  var args = slice.call(arguments, 2);
  return setTimeout(function(){ return func.apply(null, args); }, wait);
};

setTimeout によって呼び出される関数に好きなだけ多くの引数を渡すことができ追加のボーナス (まあ、通常はボーナス) として、関数に渡される引数の値は、setTimeout を呼び出すときに凍結されるため、値が変更された場合setTimeout() が呼び出されてからタイムアウトになるまでの間のある時点で、まあ...もうそれほどひどくイライラすることはありません:)

これは、私が何を意味するかを見ることができるフィドルです。

于 2012-12-18T14:28:54.343 に答える
27

ホブリンはすでにこの質問についてコメントしていますが、それは本当に答えになるはずです!

使用Function.prototype.bind()は、これを行うための最もクリーンで柔軟な方法です (thisコンテキストを設定できるという追加のボーナスがあります):

setTimeout(postinsql.bind(null, topicId), 4000);

詳細については、次の MDN リンクを参照してください:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041 https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function /bind#With_setTimeout

于 2013-03-25T16:34:04.130 に答える
12

交換

 setTimeout("postinsql(topicId)", 4000);

 setTimeout("postinsql(" + topicId + ")", 4000);

またはさらに良いことに、文字列式を無名関数に置き換えます

 setTimeout(function () { postinsql(topicId); }, 4000);

編集:

Brownstone のコメントは正しくありません。Firebug コンソールでこれを実行すると、意図したとおりに動作します。

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3
  window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();

setTimeoutこれは文字列を呼び出しeval()、代わりに関数を渡すため、文字列を渡さないようにする必要があるという他の人に同意していることに注意してください。

于 2009-07-27T21:16:10.117 に答える
7

setTimeout でパラメーターをサポートするための最も簡単なクロス ブラウザー ソリューション:

setTimeout(function() {
    postinsql(topicId);
}, 4000)

IE 9 以前をサポートしなくても構わない場合:

setTimeout(postinsql, 4000, topicId);

setTimeout デスクトップ ブラウザの互換性

setTimeout モバイル ブラウザーの互換性

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

于 2015-06-02T18:02:56.103 に答える
4

私はそれが古いことを知っていますが、これに私の(好みの)フレーバーを追加したかった.

これを達成するかなり読みやすい方法は、 を関数に渡すことだと思います。topicId関数は、引数を使用して内部でトピック ID を参照します。この値はtopicId、すぐに外側が変更されても変わりません。

var topicId = xmlhttp.responseText;
var fDelayed = function(tid) {
  return function() {
    postinsql(tid);
  };
}
setTimeout(fDelayed(topicId),4000);

または短い:

var topicId = xmlhttp.responseText;
setTimeout(function(tid) {
  return function() { postinsql(tid); };
}(topicId), 4000);
于 2013-11-20T11:07:20.423 に答える
4

一般に、関数を特定のパラメーターを持つコールバックとして渡す必要がある場合は、高階関数を使用できます。これは ES6 では非常にエレガントです。

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

または、someFunction最初の注文の場合:

setTimeout(() => someFunction(params), 1000); 
于 2018-02-08T02:38:10.953 に答える
3

この段階をどのように解決しましたか?

そのように:

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

setTimeout は関数への参照を待機するので、データを解釈し、データの適切なインスタンスを持つ関数を返すクロージャーで作成しました!

多分あなたはこの部分を改善することができます:

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

Chrome、Firefox、および IE でテストしたところ、うまく実行されました。パフォーマンスについてはわかりませんが、機能するために必要でした。

サンプルテスト:

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

署名を変更して、より準拠できるようにすることができます。

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

最後に、元の質問に答えます:

 myNass_setTimeOut( postinsql, 4000, topicId );

それが役立つことを願っています!

ps : 申し訳ありませんが、英語は私の母国語ではありません。

于 2013-05-28T21:33:47.437 に答える
3

エラー メッセージごとに topicId が「定義されていません」であった理由は、setTimeout が実行されたときにローカル変数として存在していたが、postinsql への遅延呼び出しが発生したときには存在しなかったことに注意してください。特に「this」をオブジェクト参照として渡すようなことを試みる場合は特に、変数の有効期間に注意を払うことが特に重要です。

setTimeout 関数の 3 番目のパラメーターとして topicId を渡すことができると聞きました。詳細はあまり示されていませんが、動作させるのに十分な情報があり、Safari で成功しています。ただし、「ミリ秒エラー」について何を意味するのかわかりません。ここでチェックしてください:

http://www.howtocreate.co.uk/tutorials/javascript/timers

于 2010-12-05T21:28:55.330 に答える
3

変数をパラメーターとして渡したい場合は、これを試してみましょう

要件が関数であり、parmas としての var である場合は、これを試してください

setTimeout((param1,param2) => { 
     alert(param1 + param2);
     postinsql(topicId);
},2000,'msg1', 'msg2')

要件がパラメーターとしての変数のみの場合は、これを試してください

setTimeout((param1,param2) => { alert(param1 + param2) },2000,'msg1', 'msg2')

これはES5とES6で試すことができます

于 2018-12-27T07:41:17.657 に答える
2

このような「apply()」のデフォルト機能を試すことができます。配列の要件として、より多くの引数を渡すことができます

function postinsql(topicId)
{
  //alert(topicId);
}
setTimeout(
       postinsql.apply(window,["mytopic"])
,500);
于 2018-06-06T10:32:41.377 に答える
0

@Jiri Vetyskaの投稿に感謝しますが、あなたの例には何か問題があります。ホバーアウトされたターゲット(これ)をタイムアウト関数に渡す必要があり、あなたのアプローチを試しました。IE9でテスト済み-動作しません。また、調査を行ったところ、ここで指摘したように、3番目のパラメーターは使用されているスクリプト言語であるようです。追加のパラメータについては言及されていません。

それで、私は@mederの答えに従い、このコードで私の問題を解決しました:

$('.targetItemClass').hover(ItemHoverIn, ItemHoverOut);

function ItemHoverIn() {
 //some code here
}

function ItemHoverOut() {
    var THIS = this;
    setTimeout(
        function () { ItemHoverOut_timeout(THIS); },
        100
    );
}
function ItemHoverOut_timeout(target) {
    //do something with target which is hovered out
}

うまくいけば、これは他の誰かにとって役立つでしょう。

于 2013-02-27T11:13:05.357 に答える
0

IE の 3 番目のオプトナル パラメーターに問題があり、クロージャーを使用すると、変数を (たとえばループで) 変更しても目的の結果が得られないため、次の解決策をお勧めします。

次のように再帰を試すことができます。

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

他に何もこれらの変数を変更しないこと、および無限再帰を避けるために適切な再帰条件を記述することを確認する必要があります。

于 2013-12-23T06:17:55.280 に答える
-2

私はあなたが欲しいと思います:

setTimeout("postinsql(" + topicId + ")", 4000);
于 2009-07-27T21:16:58.507 に答える