目次
举一个抽象点的例子:
これは私の
ホームページ ウェブフロントエンド jsチュートリアル JS の実行コンテキスト、実行スタック、イベント ループを理解する

JS の実行コンテキスト、実行スタック、イベント ループを理解する

Jul 06, 2020 am 10:39 AM
javascript 実行コンテキスト

この記事では、JavaScript の実行コンテキスト、実行スタック、イベント ループについて説明します。一定の参考値があるので、困っている友達が参考になれば幸いです。

JS の実行コンテキスト、実行スタック、イベント ループを理解する

次の概念は、実行コンテキストであっても、実行スタックであっても、仕様では非常に抽象的です。想像に頼った内容が多いので、間違いがあればご指摘ください。

実行コンテキスト

要するに、実行コンテキスト (実行コンテキスト) は、実行可能コードが実行されている環境を抽象化したものです。コード ブロック内の変数の評価をトレースします。これは私がまとめた概念であり、多少不正確な部分があるかもしれませんが、実際の標準定義を参照することもできます。

ただし、一般に、重要な点が 3 つあります。

  • 実行可能コードのみが実行コンテキストを持ちます

  • 実行コンテキストステートフル: 実行状態 (Perform)、一時停止状態 (Suspend)、および再開 (Resume)。 Perfrom 状態の実行コンテキストは、実行中の実行コンテキスト (Running Execution Context) と呼ばれます。

  • 実行コンテキスト は、字句環境とまったく同等ではありません。関係性を言うのは難しいですが、前者が後者を引用しているだけです。

  • JS スクリプトを実行する場合、複数の実行コンテキストが存在する可能性がありますが、実行コンテキストは 1 つだけです (非同期の場合も同様です。なぜ 4 つ挙げられているかについては、 ..3 四大王がいるのは常識ではないでしょうか...)。

そして、ES 仕様では、実行可能コードが次のように規定されています:

  • グローバル コード

  • 関数コード

  • Eval文

  • モジュールコード

その他つまり、次のコードを見てください:

  
  var g=111
  function f(){
      
      console.log(g);
      for(let i =0; i  上記のコードを実行すると、2 つの実行コンテキストのみが生成されます: <p></p>
ログイン後にコピー
  • global

  • Function

    f

  • ##ただし、
(*)

とマークされた行をコメントアウトすると、実行コンテキストは 1 つだけになります。関数 f はまったく実行されず、当然、対応する実行コンテキストも存在しないためです。この中で唯一紛らわしいのは、これが for ループ であることですが、 これはまったく実行可能コードではないため、関数実行コンテキストの一部です

実行コンテキストの重要なコンポーネント

実行コンテキストは次のように抽象化できます:

ExecutionContext = {
    State: 
    LexEnv = {
        This: ,
        OuterEnv: ,
        DecRec:{
            //... identifiername-variable
        }      
    }
    VaEnv = {
        This: ,
        OuterEnv: ,
        VarRec:{
            //... identifiername-variable
        }      
    }
}
ログイン後にコピー

実際には、実行コンテキストには 2 つあります。非常に重要です。コンポーネント:

LexicalEnvironmentComponent

(字句環境コンポーネント) および VariableEnvironmentComponent (変数環境コンポーネント)。字句環境コンポーネントは 現在のコード字句環境 (LexEnv) を指し、変数環境コンポーネントは ## の 変数環境を指します。 #現在のコード (VarEnv)。 実行コンテキストについていくつか言わなければならないことがあります。非常に重要な部分の 1 つは

スコープ チェーン

ですが、実行コンテキスト##には関連するコンテンツはありません#で見られました。ただし、 スコープ チェーン は存在します。これは [[Scope]] 内部プロパティにあり、 ブラウザ を通じて直接確認できます。 しかし、このように理解することもできます。実行コンテキストが作成されると、現在の語彙環境の LexEnv だけでなく、LexEnv.OutEnv# も作成されます。 ##, ## が作成され、 #LexEnv.OutEnv.OutEnv

… 全世界に広がるまで。

実行コンテキストの作成と破棄1. 新しい実行コンテキスト (ExecutionContext、EC) を作成します。

2. 現在のレキシカル環境を作成します ( LexEnv および VarEnv)

3. 実行コンテキストの LexicalEnvironmentComponent

および

VariableEnvironmentComponent

を次の

LexEnv

および

VarEnv## にポイントします。現在の環境。#middle. 4. 新しい実行コンテキストを 実行スタックにプッシュし、ランタイム実行コンテキストになります。 5. 実行可能コード ブロック内の識別子をインスタンス化して初期化します:

現在の字句環境で宣言されたすべての識別子を収集します #Into DecRec

,

var

で宣言されたすべての識別子は、
    VarNames
  • コレクションに含まれています。この段階では、識別子が # で宣言されている場合、

    識別子名 が検出処理されます。 ##let/const/...VarNames の識別子と同じである場合、エラーが報告されます。 DecRec で識別子をインスタンス化し、uninitialized に設定します。 VarNames の識別子は

    ObjRec
  • にバインドされ、インスタンス化後に
  • unknown

    に直接初期化されます。

  • 对于function声明的函数,将直接指向函数对象,并也会绑定到ObjRec中,这是浏览器默认行为

6、运行代码。

  • 非var声明的标识符会在声明处进行初始化(默认为undefined)。

  • 完成所有变量的赋值,并可能会一直在变化。

7、运行完毕从 执行栈 中弹出。

备注:

  • 关于This绑定,大部分情况可以用过去的说法解释,然而某些情况下却不尽然。
  • 闭包我会在下一篇介绍。
  • 执行上下文,我个人认为并不如何重要,但是却能在许多情形下起到极为关键的作用,所以还是有必要去深入认识一下。
  • 关于执行上下文和词法环境的关系,最多是前者引用了后者,仅此而已。诚然,有许多情况没必要用执行上下文来说明,但是永远避免不了违和感

执行栈与事件循环

执行栈(Execution Stack)就是由执行上下文构成的堆栈,类似于Call Stack

1、当Javascript引擎遇到一段可执行代码时,新建一个执行上下文。

2、将它推入执行栈中。并设置为运行时执行上下文。

  • 如果存在其他执行上下文。
  • 那么将当前执行上下文挂起
  • 然后再将新执行上下文推入执行栈中。

3、执行上下文运行完毕,弹出销毁恢复并将原执行上下文设为运行时。

总觉得这些没什么好说的,但是水一下吧

执行栈最重要的部分并非是执行栈概念本身,而是与任务队列的关系,它是事件循环的入门关键概念之一

众所周知,Javascript语言是单线程的,此处的执行栈就相当于主线程的调用栈,也是唯一一个调用栈,至于什么是主线程可以查阅相关资料,这里有些超纲了……

那么javascript是如何实现异步的

确切来说,这不是Javascript核心的部分,它是结合浏览器API(如Web Worker, Browser-context了解一下)实现的

事件循环中(事件处理过程),有两个极其重要的概念:

  • 任务序列: Task Quenue
  • 事件: Event

这两个概念,是抽象滴。

在Javascript中,一个任务也可以称之为事件,通常是一个函数回调,由许多任务组成的队列,就是所谓的任务序列了。任务序列有很多分类,例如:作业序列(Job Quenue)、消息序列(Message Quenue),本质没区别。

不必再深入了解,现在需要记住的是:一个任务序列中的任务如果想要被执行,就必须将它取出放入执行栈中。

举一个抽象点的例子:

例如下面的代码:

  
      var temp = 10;
      
      console.log('push task1');
      setTimeout(function task1(){
        temp+=10;
        console.log(temp+'task1 okay! ');
      },1000)
      
      console.log('taskquenue=[task1]; push task2');
      setTimeout(function task2(){
        temp*=10;
        console.log(temp+'task2 okay! ');
      },500) 
     
      console.log('taskquenue=[task1,task2]; push task3');
      setTimeout(function task3(){
        temp*= -0.2;
        console.log(temp+'task3 okay! ');
      },1500)
      console.log('taskquenue=[task1, task2,task3]');
ログイン後にコピー

输出如下:

push task1
taskquenue=[task1]; push task2
taskquenue=[task1,task2]; push task3
taskquenue=[task1, task2,task3]
100task2 okay! 
110task1 okay! 
-22task3 okay!
ログイン後にコピー

setTimeout是一个定时器,它能够将任务放到任务队列中。如图:

  • 添加作业task1
    JS の実行コンテキスト、実行スタック、イベント ループを理解する
  • 添加作业task2
    JS の実行コンテキスト、実行スタック、イベント ループを理解する
  • 添加作业task3
    JS の実行コンテキスト、実行スタック、イベント ループを理解する

执行到此处, task1task2task3都被放入了任务队列; 然后执行栈全部执行完毕后,开始处理任务队列中的任务。

为什么任务队列中的任务必须在执行栈空时后执行呢?

  • 結局のところ、これは本当に根本的な内容に関係しているので、ここではわかりません。なぜこのようになるのかは理解できますが、他の人を誤解させるのが心配なので、忘れてください。
  • 一般的に、タスク シーケンス に関連する概念はそれほど単純ではなく、ブロッキングスケジュール(これらの側面については、C Java などの他のマルチスレッド言語を参照するか、オペレーティング システムの内容を確認することができます。
  • 単純な ビジネス実装 であれば、基礎となる多くのことを知る必要はありません。

ここでタスクの処理を開始します:

  • Processingtask2:
    JS の実行コンテキスト、実行スタック、イベント ループを理解する
  • Processingtask1
    JS の実行コンテキスト、実行スタック、イベント ループを理解する
  • 処理 task3
    JS の実行コンテキスト、実行スタック、イベント ループを理解する

わかりました、イベント ループ# # #それでおしまい。 その後、
Javascript エンジンは スリープ フェーズに入ります (Javascript エンジンは終了しません!)、新しいタスクが実行されるのを待ってから、次のイベントを開始しますループ。 備考:

    これは単なる単純な例です
  • イベント ループには複数のタスク キューを持つことができます
  • タスクシーケンスにはマイクロタスク シーケンスとマクロタスク シーケンスの 2 種類があります。
  • 今回のスクリプト コードはマクロタスク シーケンスの 1 つです。
  • 最後に: Javascript エンジン

これは私の

精読 Javascript シリーズです

3 番目の記事、不意を突かれた イベント ループ 、一度に多くのことを深く掘り下げるようです...しかし、これは最も 不合理なプログラミング配置だと思います。ほとんどのドキュメントでは、タスク シーケンスコール スタック#が分離されています。 ## ですが、~~_____~~ では、これらは 1 つである必要があり、都合のよい理由で分離してはなりません JavaScript の詳細については、仕様を読むだけでなく、JS エンジン の実装ドキュメントも読むことをお勧めします。一部の高度な内容は仕様には含まれていませんが、これらのドキュメントには含まれています。ドキュメント (Google で検索してください。Baidu でも検索できます)。

JavaScript エンジン に興味がある場合は、次を参照してください:

MDN About_JavascriptChromium V8 リファレンス

    Github V8
  • とはいえ、初心者が V8 のソースコードを一気に見るのはあまりお勧めできませんが、頭が割れるような感覚と全身が震える感覚はとても楽しいです。 ……
推奨関連チュートリアル:

JavaScript ビデオ チュートリアル

以上がJS の実行コンテキスト、実行スタック、イベント ループを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 Dec 17, 2023 am 08:41 AM

JavaScript は Web 開発で広く使用されているプログラミング言語であり、WebSocket はリアルタイム通信に使用されるネットワーク プロトコルです。 2 つの強力な機能を組み合わせることで、効率的なリアルタイム画像処理システムを構築できます。この記事では、JavaScript と WebSocket を使用してこのシステムを実装する方法と、具体的なコード例を紹介します。まず、リアルタイム画像処理システムの要件と目標を明確にする必要があります。リアルタイムの画像データを収集できるカメラ デバイスがあるとします。

See all articles