いくつかの面接の質問を使って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を使用して無料の証明書を生成する方法

推薦する

Docker ポート マッピングと外部アクセス不可の問題

Docker コンテナはサービスを提供し、ポート 8888 をリッスンします。外部からアクセスできる...

HTMLのmarquee属性でテキストを踊らせる

構文: <marquee> …</marquee>モバイル属性マーキーを使用...

Nginx で HTTPS 証明書を構成する詳細なプロセス

1. HttpとHttpsの違いHTTP: インターネットで最も広く使用されているネットワーク プロ...

Linux仮想メモリについての簡単な説明

目次起源仮想メモリページングとページテーブルメモリのアドレス指定と割り当て関数プロセスメモリ管理デー...

MySQL データベースの 1045 エラーの解決方法

ローカル データベースがサーバー データベースに接続されているときに発生する 1045 の問題を解決...

Vueプロジェクトでlessを使用するためのヒント

目次序文1. スタイルの浸透1. パターン浸透とは何ですか? 2. 使い方は? 2. ミキシング1....

CentOS に MySQL をインストールしてリモート アクセスを設定する方法

1. MySQLリポジトリソースをダウンロードする$ wget http://repo.mysql....

CentOS で新しいユーザーを作成し、キーログインを有効にする方法

目次新しいユーザーを作成する新規ユーザーを承認する新規ユーザーのSSHキーログインを有効にする他のS...

MySQLデータベースインデックスの詳細な説明

目次1. MySQLインデックスの紹介2. MySQLの5種類のインデックスの詳しい説明1. 総合索...

VMware Workstation のインストール Linux (Ubuntu) システム

システムをコンピューターにインストールする方法がわからない場合は、Linux を学習したい場合は、仮...

データベースアカウントのパスワード暗号化の詳細な説明と例

データベースアカウントのパスワード暗号化の詳細な説明と例データベースアカウントとパスワードはデータベ...

Win7 の VMware 仮想マシンに Linux7.2 をインストールするインターネット アクセス構成チュートリアル

参考までに、win7システム上のVMware仮想マシンにlinux7.2インターネットアクセス構成を...

MySQL InnoDB ストレージ エンジンの詳細

序文MySQL では、InnoDB はストレージ エンジン レイヤーに属し、プラグインとしてデータベ...

Vueはログイン認証コードを実装する

この記事では、ログイン認証コードを実装するためのvueの具体的なコードを例として紹介します。具体的な...

MySQL v5.7.18 解凍バージョンのインストール詳細チュートリアル

MySQLをダウンロード5.1.1.1 より前のバージョン私のコンピュータは64ビットなので、Win...