検索
ホームページウェブフロントエンドjsチュートリアルJS の実行コンテキスト、実行スタック、イベント ループを理解する

この記事では、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 サイトの他の関連記事を参照してください。

声明
この記事はcsdnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
JavaScriptの役割:WebをインタラクティブでダイナミックにするJavaScriptの役割:WebをインタラクティブでダイナミックにするApr 24, 2025 am 12:12 AM

JavaScriptは、Webページのインタラクティブ性とダイナミズムを向上させるため、現代のWebサイトの中心にあります。 1)ページを更新せずにコンテンツを変更できます。2)Domapiを介してWebページを操作する、3)アニメーションやドラッグアンドドロップなどの複雑なインタラクティブ効果、4)ユーザーエクスペリエンスを改善するためのパフォーマンスとベストプラクティスを最適化します。

CおよびJavaScript:接続が説明しましたCおよびJavaScript:接続が説明しましたApr 23, 2025 am 12:07 AM

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

Webサイトからアプリまで:JavaScriptの多様なアプリケーションWebサイトからアプリまで:JavaScriptの多様なアプリケーションApr 22, 2025 am 12:02 AM

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Python vs. JavaScript:ユースケースとアプリケーションと比較されますPython vs. JavaScript:ユースケースとアプリケーションと比較されますApr 21, 2025 am 12:01 AM

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

JavaScript通訳者とコンパイラにおけるC/Cの役割JavaScript通訳者とコンパイラにおけるC/Cの役割Apr 20, 2025 am 12:01 AM

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

JavaScript in Action:実際の例とプロジェクトJavaScript in Action:実際の例とプロジェクトApr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptとWeb:コア機能とユースケースJavaScriptとWeb:コア機能とユースケースApr 18, 2025 am 12:19 AM

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンの理解:実装の詳細JavaScriptエンジンの理解:実装の詳細Apr 17, 2025 am 12:05 AM

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

See all articles

ホット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 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!