引用符と括弧の有無によるsetTimeoutの違い


240

私はJavaScriptを学習していますが、JavaScriptのタイミングイベントについて最近学びました。W3Schoolsで知ったとき、今setTimeoutまで出会ったことのない奇妙な姿に気づきました。彼らは二重引用符を使用してから、関数を呼び出します。

例:

setTimeout("alertMsg()", 3000);

JavaScriptの二重引用符と単一引用符は文字列を意味することを知っています。

また、私はそのように同じことができることがわかりました:

setTimeout(alertMsg, 3000);

括弧が付いている場合はそれを参照しており、括弧がない場合はコピーされます。引用符とかっこを使用していると、頭がおかしくなります。

これらの3つの使用方法の違いを誰かに説明してもらえたら嬉しいですsetTimeout

括弧付き:

setTimeout("alertMsg()", 3000);

引用符と括弧がない場合:

setTimeout(alertMsg, 3000);

そして、3番目は引用符のみを使用しています。

setTimeout("alertMsg", 3000);

注意:setTimeout参照のためのより良い情報源はMDNです。


5
@Jefffreyのw3fools Webサイトは、そこにあるコンテンツが間違っているとは言っていません。ただ、古くて新しいもののいくつかが欠けている可能性があるだけです。コアとなるもののリファレンスとして使用する(または学習する)には問題ありません。彼らがw3の一部であるかのように見せかけようとしていることに不満を抱いている人々を理解できますが、それはコンテンツを損なうものではありません。それは見事にレイアウトされ、わかりやすい例で読みやすく、初心者に最適です。
マシュー

14
@マシュー「しかし、私たちはW3Schoolsが不正確な情報でコミュニティを傷つけていると感じています。」-最初の3行内。

1
@Jefffreyええ、私はそれを見ましたが、「W3Schoolsは問題です」セクションで、彼らがそれについて好きではないことを説明するところを低くします。彼らは実際に「間違っている」何かの単一の例を持っていません。彼らの不満は、彼らがw3と提携していないことを明示的に述べておらず、認識されていない証明書に対して請求し、新しいコンテンツ(html 5など)で迅速に更新しないことです。
マシュー

10
@マシュー、Javascript、SQL、PHPなどの繊細な言語の古い情報はmysql_、SOの質問ストリームが単なる例である、古くて潜在的に危険なテクノロジー(PHP の拡張など)にこだわるように意欲的なプログラマの大衆を導くものです。IIRCでもSQLセクションに非常に微妙な誤りがいくつかありましたが、最後にWebサイトにアクセスしてからほぼ1年が経ち、多くの問題が修正される可能性もあります。そして、上記のすべてが完璧だったとしても、証明書の詐欺で人々を欺こうとするウェブサイトを宣伝することはしません。
靴の

4
怪しげな認証はさておき、それはまともな参照リソースであり、非難することはSOの全体的なポイントに対して逆効果です。
2013

回答:


382

setIntervalまたはを使用するsetTimeout

setTimeoutまたはの最初の引数として関数への参照を渡す必要がありますsetInterval。この参照は、次の形式になります。

  • 匿名関数

    setTimeout(function(){/* Look mah! No name! */},2000);
  • 既存の関数の名前

    function foo(){...}
    
    setTimeout(foo, 2000);
  • 既存の関数を指す変数

    var foo = function(){...};
    
    setTimeout(foo, 2000);

    「関数の変数」は「関数名」とは別に設定しています。変数と関数名が同じ名前空間を占め、お互いに混雑する可能性があることは明らかではありません。

引数を渡す

関数を呼び出してパラメーターを渡すには、タイマーに割り当てられたコールバック内で関数を呼び出すことができます。

setTimeout(function(){
  foo(arg1, arg2, ...argN);
}, 1000);

ハンドラに引数を渡す別の方法がありますが、 ブラウザー間の互換性はありません

setTimeout(foo, 2000, arg1, arg2, ...argN);

コールバックコンテキスト

デフォルトでthisは、実行時のコールバックのコンテキスト(タイマーによって呼び出される関数内の値)はグローバルオブジェクトです。windowです。変更したい場合は、を使用してくださいbind

setTimeout(function(){
  this === YOUR_CONTEXT; // true
}.bind(YOUR_CONTEXT), 2000);

安全保障

可能ですが、またはに文字列渡すべきではありません。文字列を渡すと、スクリプトとして文字列実行するのと同様の機能が作成または使用され、任意の、潜在的に有害なスクリプトの実行が可能になります。setTimeoutsetIntervalsetTimeout()setInterval()eval()


関数名のみを使用している場合、関数がコピーされることを学びました。最初の例で、なぜsetTumeout foo(関数)パス参照が関数をコピーしたと言うのですか?evalについてもっと教えてください。
user1316123 2012

41
@ user1316123関数はコピーされません。オブジェクトや配列と同じです。それらは参照渡しされます。あなたはw3schoolsを読むのをやめるべきです。彼らは善よりも害を及ぼしている
ジョセフ

4
@JosephtheDreamer関数オブジェクトです。「関数名」と「関数を参照する変数」は同じものです。また、パラメータをsetTimeoutに直接渡すこともできます(ラムダでラップする必要はありません(以前の言ったように、新しいブラウザです)。また、問題は、ユーザーがスクリプトを実行できるようにすることではありません(とにかくいつでもこれを実行できます)。他のユーザーから入力を受け入れ、それをスクリプトとして実行することにより、ユーザー自身がいつでもコンソールを開いて任意のJavaScriptを実行できます
Benjamin Gruenbaum

@BenjaminGruenbaum私はあなたの2番目の文とほぼ同じコメントをしようとしていました。笑う:)
ErikE 2013

2
setTimeoutが正しく機能するための関数を使用する必要があることに気づきませんでした。それを片付けてくれてありがとう。
Matt Dell

3

あなたが書いたsetTimeout関数が実行されていないと思います。jqueryを使用する場合は、次のようにして正しく実行できます。

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });

私はあなたと同じように考えていますが、リンクw3schools.com/js/js_timing.aspが他の場所にいると言っています
user1316123

ブラケットを使用しているときに正しく理解できれば、setTimeoutメソッドを含む関数のみを参照できます。これは、関数がローカルスコープでのみブラケットで使用できるためです。
user1316123 2012

2

ジョセフに完全に同意します。

これをテストするためのフィドルです: http //jsfiddle.net/nicocube/63s2s/

フィドルのコンテキストでは、関数がグローバルスコープで定義されていないため、文字列引数は機能しません。


w3schools.com/js/js_timing.aspリンクを入力できる場合は確認してください。ジョセフは危険だと言いますが、リンクを入力した場合は機能します
user1316123 '25

みんなこれを見てください:quirksmode.org/js/this.htmlこのリンクはfuncをコピーできることを示しています
user1316123 '25

はい、できます。JSの関数はオブジェクトです。evalの問題は、グローバルコンテキストで評価され、フィドルで発生するローカルコンテキストを取得できないことです。
ニコキューブ

evalについて少し説明していただけますか。
user1316123 2012


1

関数の最初のパラメータとして文字列を渡した場合、実際には何が起こりますか

setTimeout('string'number

実行するとき(numberミリ秒経過後)に評価される最初のパラメーターの値です。基本的には

setTimeout(eval('string')number

これは

関数の代わりに文字列を含めることができる代替構文。タイマーが切れたときにコンパイルおよび実行されます。この構文は、eval()の使用をセキュリティリスクにする同じ理由で推奨されていません。

したがって、あなたが参照するサンプルは良いサンプルではなく、異なるコンテキストまたは単純なタイプミスで与えられる可能性があります。

このように呼び出す場合setTimeout(something, number)、最初のパラメータは文字列ではなく、呼び出されるものへのポインタsomethingです。そして再びsomething文字列の場合-それは評価されます。ただし、関数の場合は、関数が実行されます。 jsbinサンプル


0
    ##If i want to wait for some response from server or any action we use setTimeOut.

    functionOne =function(){
    console.info("First");

    setTimeout(()=>{
    console.info("After timeOut 1");
    },5000);
    console.info("only setTimeOut() inside code waiting..");
    }

    functionTwo =function(){
    console.info("second");
    }
    functionOne();
    functionTwo();

## So here console.info("After timeOut 1"); will be executed after time elapsed.
Output:
******************************************************************************* 
First
only setTimeOut() inside code waiting..
second
undefined
After timeOut 1  // executed after time elapsed.

-1

括弧付き:

setTimeout("alertMsg()", 3000); // It work, here it treat as a function

引用符と括弧がない場合:

setTimeout(alertMsg, 3000); // It also work, here it treat as a function

そして、3番目は引用符のみを使用しています。

setTimeout("alertMsg", 3000); // It not work, here it treat as a string

function alertMsg1() {
        alert("message 1");
    }
    function alertMsg2() {
        alert("message 2");
    }
    function alertMsg3() {
        alert("message 3");
    }
    function alertMsg4() {
        alert("message 4");
    }

    // this work after 2 second
    setTimeout(alertMsg1, 2000);

    // This work immediately
    setTimeout(alertMsg2(), 4000);

    // this fail
    setTimeout('alertMsg3', 6000);

    // this work after 8second
    setTimeout('alertMsg4()', 8000);

上記の例では、alertMsg1()(2秒の待機時間)の直後に最初のalertMsg2()関数呼び出し(タイムアウトは4Sですが、問題はありません)、次にalertMsg4()(8秒の待機時間)しかし、alertMsg3()は、パーティなしで引用符で囲んで文字列として扱われるため、機能しません。


質問者が尋ねるシナリオを示しますが、実際には質問には答えません。これが既存の6年前の回答に何を追加するのかわかりません。
スティーブンP
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.