forサイクルについてsetTimeoutを参照します.
2546 ワード
テーマ1:
このテーマはJavaScriptのシングルスレッドとset Timeoutの非同期特性を考察します.
【注】:JavaScriptエンジンは単一スレッドで実行されています.ブラウザの実行中は一つのスレッドだけがjsプログラムを実行しています.ブラウザのカーネルはマルチスレッドであり、彼らはカーネルコントロールの下で互いに協力して、同期を維持する.一つのブラウザは少なくとも三つの常駐スレッドを実現する.JavaScriptエンジンスレッド、GUIレンダリングスレッド、ブラウザイベントトリガスレッド. JavaScriptエンジンはイベントドライバの単一スレッドに基づいて実行され、Jsエンジンは常にジョブキュー中のタスクの到来を待っています.そして処理します.ブラウザはいつでもjsスレッドだけがjsプログラムを実行しています. GUIレンダリングスレッドは、ブラウザのインタフェースのレンダリングを担当しています.インターフェースが再描画される必要があるときや、ある操作によってフィードバックが生じると、GUIレンダリングスレッドとjsエンジンは相互に反発しています.Jsエンジンが実行されると、GUIスレッドは保留され、GUI更新はキューに保存されます. イベントトリガスレッドは、イベントがトリガされると、処理対象のキューの最後にイベントを追加し、jsエンジンの処理を待つ.これらのイベントは、jsエンジンが現在コードブロックを実行しており、setTimeoutのようなブラウザカーネルからの他のスレッド、マウスクリック、ajax非同期要求などがありますが、jsのシングルスレッド関係のために、これらのイベントはすべてjsエンジン処理を待ち続けなければなりません. は、スレッドに同期コードがないという前提で非同期コードを実行する. --以上の情報はhttps://www.zhihu.com/people/fredshare.
上のタイトルでsetTimeoutは非同期のコードです.setTimeoutで設定された待ち時間が0であってもすぐに実行されません.forサイクルコードは同期ですので、forサイクルが終わったらsetTimeoutを実行します.この場合、従来のforループを使用して、setTimeoutでa[i]を印刷するとundefinedが発生する場合があります.このとき、forループの外にローカル変数jを定義することができる.印刷時にa[j++]を印刷するとa配列のエルゴードが可能です.
コードは以下の通りです
var a=[1,2,3];
var len=a.length;
for(___){
setTimeout{function(){
console.log(__);
},0}
}
aを出力する全ての項目が要求されます.このテーマはJavaScriptのシングルスレッドとset Timeoutの非同期特性を考察します.
【注】:JavaScriptエンジンは単一スレッドで実行されています.ブラウザの実行中は一つのスレッドだけがjsプログラムを実行しています.ブラウザのカーネルはマルチスレッドであり、彼らはカーネルコントロールの下で互いに協力して、同期を維持する.一つのブラウザは少なくとも三つの常駐スレッドを実現する.JavaScriptエンジンスレッド、GUIレンダリングスレッド、ブラウザイベントトリガスレッド.
上のタイトルでsetTimeoutは非同期のコードです.setTimeoutで設定された待ち時間が0であってもすぐに実行されません.forサイクルコードは同期ですので、forサイクルが終わったらsetTimeoutを実行します.この場合、従来のforループを使用して、setTimeoutでa[i]を印刷するとundefinedが発生する場合があります.このとき、forループの外にローカル変数jを定義することができる.印刷時にa[j++]を印刷するとa配列のエルゴードが可能です.
コードは以下の通りです
var a=[1,2,3,4];
var i,len=a.length;
var j=0;
for(i = 0; i < len; i++) {
(function(i) {
setTimeout(function() {
console.log(a[j++]);
}, 0);
})(i)
}
或者-----http://m.blog.csdn.net/article/details?id=51177648for(i = 0; i < len; i++) { (function(i) { setTimeout(function() { console.log(a[i]); }, 0); })(i) }
テーマ2:上のコードブロックは3つの‘4’をプリントしますが、私達が予想していた結果は1、2、3をプリントします.for(var i = 1; i <= 3; i++) { setTimeout(function() { console.log(i) }, 0) } //4,4, 4
なぜかというと、setTimeoutのiは対外層iの参照であるからである.setTimeoutのコードが解釈されると、実行時はiの参照だけが記録され、値ではない.setTimeoutがトリガされると、3つのsetTimeoutのiは同時に値をとり、それらはすべて外層の同じiを指すので、そのiの値は反復が完了すると4になるので、3回の‘4’を印刷した.
私たちが予想した結果を得るために、私たちはi賦を局所的な変数にして、外層反復の影響を脱することができます.または:for (var i = 0; i <= 3; i++) { (function (idx) { setTimeout(function () { console.log(idx); }, 5); })(i); }
var j=0;
for(i = 0; i <=3; i++) { (function(i) { setTimeout(function() { console.log(a[j++]); }, 0); })(i) }