いくつかの面接の質問を使ってJavaScriptの実行メカニズムを調べる

いくつかの面接の質問を使ってJavaScriptの実行メカニズムを調べる

前の単語

JavaScript の動作環境により、単一スレッドとしてロックされ、タスクはキューに入れて実行する必要があります。Web サイトのリソースが大きい場合、これによりブラウザの読み込みが非常に遅くなりますが、実際にはそうではありません。誰もがすぐに同期と非同期を思い浮かべたはずです。

いわゆる同期と非同期もキューイングですが、キューイングする場所が異なります。

同期と非同期

同期タスクはメインスレッドにキューイングされ、非同期タスクはイベントキューにキューイングされます。

同期タスクと非同期タスクは異なるキューに入ります。これは、上で説明したように、異なる場所にキューイングされるということです。

同期タスクはメイン スレッドに入り、非同期タスクはイベント キューに入り、メイン スレッド タスクが実行された後、イベント キューで実行を待機しているタスクは、イベント キュー内のすべてのタスクが実行されるまで、メイン スレッドに入って実行されます。

前菜

コンソールログ('a')

setTimeout(関数(){
    コンソールログ('b')
}, 200)

setTimeout(関数(){
    コンソールログ('c')
}, 0)

コンソールログ('d')

アドビ

上から下に向かって、メイン スレッドに入るべきものはメイン スレッドに入り、イベント キューに入るべきものはイベント キューに入ります。

そしてメインスレッドに console.log('a') と console.log('d') があり、タイマー setTimeout によって一定時間実行が遅延されます。名前の通り、非同期タスクはイベントキューに入り、メインスレッドのタスクが実行されるまで待機し、その後メインスレッドに入って実行されます。

遅延が 0 のタイマーは、すぐに実行されるという意味ではなく、メイン スレッドに入り、他のタイマーよりも早く実行されるという意味です。

プレートを追加

(var i = 0; i < 10; i++) {
    setTimeout(関数() {
        コンソールログ(i)
    }, 1000)
}

結果: 10 10

for ループが setTimeout に遭遇するたびに、イベント キューに入れられ、すべてのループが完了するまで実行を待機します。i はグローバル変数です。ループが終了すると、i = 10 になります。setTimeout が再度実行されると、i の値はすでに 10 になっており、結果は 10 個の 10 になります。

var を let に変更します。変数のスコープが異なります。let は現在のループ内で動作するため、イベント キューに入るタイマーの i は毎回異なり、最終的な印刷結果は 0 1 2...9 になります。

マクロタスク マイクロタスク

よく言われる同期タスクと非同期タスクに加え、マクロタスクとマイクロタスクに分けることができます。

メイン マクロ タスク: スクリプト全体 scriptsetTimeoutsetTimeout...

メインのマイクロタスク: promise.then...

実行プロセス:

1. スクリプト全体がマクロタスクとして実行を開始します。

2. マイクロタスクに遭遇したら、それをマイクロタスクキューにプッシュし、マクロタスクをマクロタスクキューにプッシュします。

3. マクロタスクが実行された後、実行可能なマイクロタスクがあるかどうかを確認します。

4. 実行可能なマイクロタスクを見つけ、すべてのマイクロタスクを完了しました

5. 新しいマクロタスクを開始し、すべてのタスクが完了するまで繰り返します。

約束しましょう

const p = 新しい Promise(resolve => {
    コンソールログ('a')
    解決する()
    コンソールログ('b')
})

p.then(() => {
    コンソールログ('c')
})

コンソールログ('d')

結果: abdc

1. スクリプト全体がマクロタスクキューに入り、実行を開始します。

2. Promiseが作成され、すぐに実行され、abが印刷されます。

3. promise.thenに遭遇し、マイクロタスクキューに入る

4. console.log('d')がdを出力する場合

5. コード全体はマクロ タスクとして実行され、実行可能なマイクロ タスクがあります。マイクロ タスクは実行を開始し、c を出力します。

setTimeout(関数(){
    コンソールログ('setTimeout')
}, 0)

const p = 新しい Promise(resolve => {
    コンソールログ('a')
    解決する()
    コンソールログ('b')
})

p.then(() => {
    コンソールログ('c')
})

コンソールログ('d')

結果: abdc setTimeout

1.setTimeoutがマクロタスクキューに入る

2. Promiseが作成され、すぐに実行され、abが印刷されます。

3. promise.thenに遭遇し、マイクロタスクキューに入る

4. console.log('d')がdを出力する場合

5. 実行可能なマイクロタスクがあり、cを印刷する

6. マイクロタスクが実行された後、新しいマクロタスクの実行が開始され、setTimeoutの実行が開始され、setTimeoutが印刷されます。

setTimeout(関数(){
    コンソールログ('setTimeout')
}, 0)

const p = 新しい Promise(resolve => {
    コンソールログ('a')
    解決する()
    コンソールログ('b')
})

p.then(() => {
    コンソールログ('c')
    setTimeout(関数(){
        console.log('setTimeout in then')
    }, 0)
})

コンソールログ('d')

結果: abdc setTimeoutのsetTimeout

1. 上記と同じ

2. cを印刷するマイクロタスクを実行し、setTimeoutに遭遇したときにマクロタスクキューにプッシュします。

3. タイマー遅延時間は同じで、マクロタスクが順番に実行され、setTimeoutthen の setTimeout がそれぞれ出力されます。

タイマーを追加する

コンソールにログ出力します。

新しいPromise(resolve => {
    コンソールログ('b')
    解決する()
}).then(() => {
    コンソールログ('c')
    タイムアウトを設定する(() => {
      コンソールログ('d')
    }, 0)
})

タイムアウトを設定する(() => {
    コンソールログ('e')
    新しいPromise(resolve => {
        コンソールログ('f')
        解決する()
    }).then(() => {
        コンソールログ('g')
    })
}, 100)

タイムアウトを設定する(() => {
    コンソールログ('h')
    新しいPromise(resolve => {
        解決する()
    }).then(() => {
        コンソールログ('i')
    })
    コンソールログ('j')
}, 0)

結果: abchjidefg

1. 印刷する

2.promiseはすぐに実行され、bを出力します。

3.promise.thenはマイクロタスクキューにプッシュします

4.setTimeoutはマクロタスクキューにプッシュします

5. コード全体が実行されると、マイクロタスクが実行を開始し、cを印刷し、setTimeoutに遭遇すると、マクロタスクキューにプッシュされ、実行を待機します。

6. 実行可能なマイクロタスクがない場合、マクロタスクの実行を開始し、タイマーは遅延時間に従って実行のためにキューに入れられます。

7. hj、promiseを印刷し、マイクロタスクキューにプッシュします。

8. 実行可能なマイクロタスク、i を印刷、マクロタスクの実行を続行、d を印刷

9. マクロタスクを100の遅延で実行し、efを印刷し、マイクロタスクを実行してgを印刷すると、すべてのタスクが完了します。

簡単なテスト

コンソールログ('開始')

a().then(() => {
  コンソールログ('a_then')
})

コンソールログ('終了')

関数a() {
  コンソールログ('a_function')
  b() を返します。その後 ((res) => {
    コンソールログ('res', res)
    コンソールログ('b_then')
    return Promise.resolve('メソッド a の戻り値')
  })
}

関数b() {
  コンソールログ('b_function')
  Promise.resolve('戻り値') を返します。
}

結果: start a_function b_function end res return value b_then a_then

上記の例のプロセスに沿って考え、理解を深めてください

要約する

  • JavaScriptはシングルスレッドであり、タスクは実行のためにキューに入れる必要がある
  • 同期タスクはメイン スレッド キューに入り、非同期タスクはイベント キューに入り、実行のためにメイン スレッドにプッシュされるのを待機します。
  • 遅延が 0 の行タイマーは、すぐに実行されるわけではなく、他のタイマーよりも早く実行されます。
  • マクロタスクとマイクロタスクによる js 実行メカニズムをさらに理解する
  • コード全体はマクロタスクとして実行を開始します。実行中、マクロタスクとマイクロタスクは対応するキューに入ります。
  • コード全体の実行が完了したら、マイクロタスクキューに実行待ちのタスクがあるかどうかを確認します。ある場合は、マイクロタスクキューのタスクが完了するまですべてのマイクロタスクを実行します。ない場合は、続行します。
  • 新しいマクロ タスクを実行します。マクロ タスクの実行中にマイクロ タスクが検出されると、そのタスクは実行のためにマイクロ タスク キューにプッシュされます。
  • すべてのタスクが完了するまでこのプロセスを繰り返します。

上記は、いくつかの面接の質問を使用して JavaScript 実行メカニズムの詳細を確認したものです。JavaScript 実行メカニズムの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • JavaScriptイベント実行メカニズムの深い理解
  • JavaScript実行メカニズムの詳細な説明
  • JavaScriptの実行メカニズムを徹底的に理解する
  • JavaScript実行メカニズムの詳細な紹介

<<:  MySQL レプリケーションの利点と原則を詳しく説明します

>>:  opensslを使用して無料の証明書を生成する方法

推薦する

CSS3で実装されたグラデーションスライド効果

成果を達成する コードhtml <div class="css-slideshow&...

DockerはホストのMysql操作に接続します

今日、会社のプロジェクトでは docker を設定する必要があります。Windows に正常にインス...

HTMLはテキスト行のインターセプトの実装原理とコードを超えています

複数行を超えるテキストをインターセプトするための HTML コードは次のとおりです。 HTML:コー...

Node.js のフロントエンドとバックエンドのインタラクションによるユーザーログインの実装の実践

目次1. プロジェクト要件次にコーディングを始める1. フロントエンドページを作成する(CSSスタイ...

dockerコンテナがIP経由でホストマシンにアクセスできない問題を解決する方法の詳細な説明

問題の起源docker を使用する場合、残念ながら docker コンテナ内のホストのポート 80 ...

CSS3 のフレックスレイアウト幅の無効性の解決策

2 列レイアウトはプロジェクトでよく使用されます。この効果を実現する方法はたくさんあります。 しかし...

IE9 のネイティブ ページ互換性の問題に対する解決策についての簡単な説明

序文最近、クライアントのネイティブページを引き継ぎました。顧客は、ページが IE9 以降のバージョン...

HTML+CSSプロジェクト開発経験概要(推奨)

ここ数日ブログを更新していませんでした。簡単な HTML+CSS プロジェクトを終えたところです。数...

VUE+Canvasは、インゴットを受け取る富の神のゲームを実装します

前回のキャンバス ゲーム シリーズへようこそ: 《VUEがFlappy Birdを実装しました〜〜〜...

MySQLログシステムの使い方に関する簡単なチュートリアル

目次序文1. エラーログ2. バイナリログ1. バイナリログを有効にする2. バイナリログ形式3. ...

MySQL 5.7 クラスタ構成手順

目次1. サーバーAのmy.cnfファイルを変更する2. サーバーBのmy.cnfファイルを変更する...

Reactドラッグフックを実装するための100行以上のコード

序文ソースコードは合計で 100 行強しかありません。これを読めば、react-dnd などの成熟し...

MySQLとNavicatプレミアムのインストールと設定の詳細な手順

前提条件: Mac、zsh がインストールされ、bash のときに mysql がダウンロードされ、...

MySQL 8.0.17 のインストールと設定のグラフィックチュートリアル

この記事は、参考のためにMySQL 8.0.17のインストールと設定のグラフィックチュートリアルを記...

MySQL 8.0 の降順インデックス

序文インデックスが順序付けられていることは誰もが知っていると思いますが、MySQL の以前のバージョ...