次のコードを読んで、実行の結果を推測してください。
var start = new date; setimeout(function(){console.log( 'time pass:'+(new date -start)+'msec');}、200); while(new Date -start <1000){} console.log(1); function dosoming(){settimeout(function(){console.log( 'time pass again:'+(new date -start)+'msec');}、10);} dosoming(); while(new Date -Start <2000){} Console.Log(2);消す:
約1秒後の出力:1、
約1秒後、出力は次のとおりです。
その後、すぐに出力:時間が経過しました:2002ミリ秒
最終出力:再び時間が経過しました:2003ミリ秒
あなたはそれを正しく推測しましたか?
ここでは、SettimeOutによる実行を遅らせるすべての機能は、実行前に最後までプッシュされます。
原則は次のとおりです。
既存のブラウザ環境では、JavaScript実行エンジンはシングルスレッドです。メインスレッドのステートメントとメソッドは、タイミングタスクの実行をブロックします。 JavaScript実行エンジンの外には、タスクキューがあります。 CodeでSettimeout()メソッドが呼び出されると、登録された遅延メソッドがブラウザカーネル内の他のモジュールに処理のために掛けられます。遅延メソッドがトリガー条件に到達すると、つまり、セット遅延時間がセットに到達すると、モジュールはモジュールのタスクキューに実行するメソッドを追加します。このプロセスは、実行エンジンのメインスレッドとは無関係です。実行エンジンは、メインスレッドメソッドが実行され、アイドル状態に到達するときに実行するために、モジュールのタスクキューから順番にタスクを抽出します。この期間の時間は、タスクを登録するときに設定された遅延時間よりも大きい場合があります。
ブラウザがアイドル状態の場合、イベントループモデルと呼ばれるモジュールのタスクキューからタスクを常に抽出しようとします。
前のコードを振り返ってみましょう。 2番目のSettimeOut()遅延方法の遅延時間は10ミリ秒で、最初のSettime owsよりも早くトリガーされます。実行結果が遅れているのはなぜですか?以前のコードによって約1000.5〜1001ミリ秒(ブラウザの処理速度に応じて)、処理モジュールに固執し、トリガー時間がタスクキューに追加されると、最初のSettimeOut()遅延方法がモジュールのタスクチームに長く追加され、メインエンジンスレッドは順番に取得されます。
さて、上記のwhile(new Date -Start <1000){}をwhile(new Date -Start <189){}またはwhile(new Date -Start <190){}に変更した場合、結果は何ですか?あまり言わない!ブラウザをそれぞれ20回更新して、結果を自分で確認してください!
setInterval()メソッドとsettimeout()は同じステータスを持っています。 SetInterval()メソッドが呼び出されると、登録された遅延メソッドが処理のためにモジュールに掛けられます。トリガー時間が到着するたびに、実行する方法が1回タスクキューに追加されます。
Settimeoutの構文を見てみましょう。
var timeId = window.settimeout(func、delay、[param1、param2、...]);
var timeId = window.settimeout(code、delay);
SettimeOutとSetIntervalは、ウィンドウオブジェクトの方法です(ウィンドウは省略できます)。 2番目のオプションのパラメーター(IE9および古いバージョンではサポートされていません)は、FUNCに渡されるパラメーターです。それらが呼び出されるたびに、数値IDが返されます(これはブラウザに印刷された数字にすぎませんが、WebStormで印刷し、実際には多くの属性を持つオブジェクトであることがわかりました)。このIDは、対応するSettimeOutまたはSetIntervalの関連情報を維持し、主に中央のモジュールとタスクキュー(Method ClearTimeout(ID)およびClearInterval(ID)を使用)でそれらをクリア(または閉じる)に使用します。
パラメーターをコールバック関数に渡す必要がある場合、以下はIE互換のライティング方法です
if(document.all &&!window.settimeout.ispolyfill){var __nativest__ = window.settimeout; window.settimeout = function(vcallback、ndelay、param1、param2、param3){var aargs = array.prototype.slice.call(arguments、2); return __nativest __(vcallback instanceof function?function(){vcallback.apply(null、aargs);}:vcallback、ndelay); }; window.settimeout.ispolyfill = true;}ループで閉鎖を使用するときに一般的なエラーが発生します
for(var i = 0; i <10; i ++){setimeout(function(){console.log(i);}、1000);}上記のコードでは、10回10回出力されます。なぜ?閉鎖!
console.logが呼び出されると、匿名関数は外部変数Iへの参照を維持していますが、この時点でforループは終了し、iの値は10に変更されます。
目的の結果を取得するには、各ループで作成する必要がある変数のコピーを取得します。
ループ番号を正しく取得するには、匿名のラッパーを使用することが最善です(実際、通常は自己実行匿名関数と呼ばれるもの)。
for(var i = 0; i <10; i ++){(function(e){setimeout(function(){console.log(e);}、1000);})(i);}外部匿名関数はすぐに実行され、そのパラメーターとして使用されます。この時点で、関数のE変数にはiのコピーがあります。
SettimeOutに渡された匿名関数が実行されると、Eへの参照があり、この値はループによって変更されません。
同じ仕事をする別の方法があります。つまり、匿名のラッパーから関数を返すことです。これは、上記のコードと同じように機能します。
for(var i = 0; i <10; i ++){setimeout((function(e){return function(){console.log(e);}})(i)、1000)}別の重要なアプリケーション:関数スロットルと関数のデバウンス
インターネットから収集した情報をご覧ください。
JavaScript-パフォーマンス最適化関数スロットルと関数のデバウンス
参照リンク:
https://developer.mozilla.org/zh-cn/docs/web/api/window/settimeout
http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout-said-the-event-loop-model/#prettyphoto
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。