この記事では、JavaScript の実行コンテキスト、実行スタック、イベント ループについて説明します。一定の参考値があるので、困っている友達が参考になれば幸いです。
次の概念は、実行コンテキスト
であっても、実行スタック
であっても、仕様では非常に抽象的です。想像に頼った内容が多いので、間違いがあればご指摘ください。
実行コンテキスト
要するに、実行コンテキスト (実行コンテキスト) は、実行可能コードが実行されている環境を抽象化したものです。コード ブロック内の変数の評価をトレースします。これは私がまとめた概念であり、多少不正確な部分があるかもしれませんが、実際の標準定義を参照することもできます。
ただし、一般に、重要な点が 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) を作成します。
3. 実行コンテキストの LexicalEnvironmentComponent
およびVariableEnvironmentComponent
を次のLexEnv
およびVarEnv## にポイントします。現在の環境。#middle. 4. 新しい実行コンテキストを
実行スタック
にプッシュし、ランタイム実行コンテキスト
になります。 5. 実行可能コード ブロック内の識別子をインスタンス化して初期化します:
現在の字句環境で宣言されたすべての識別子を収集します #Into DecRec
var
で宣言されたすべての識別子は、- VarNames
- コレクションに含まれています。この段階では、識別子が # で宣言されている場合、
識別子名 が検出処理されます。 ##let/const/... が VarNames の識別子と同じである場合、エラーが報告されます。
ObjRecDecRec で識別子をインスタンス化し、
uninitialized
に設定します。VarNames
の識別子は にバインドされ、インスタンス化後に - 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
: - 添加作业
task2
: - 添加作业
task3
:
执行到此处, task1
、task2
和task3
都被放入了任务队列; 然后执行栈全部执行完毕后,开始处理任务队列中的任务。
为什么任务队列中的任务必须在执行栈空时后执行呢?
- 結局のところ、これは本当に根本的な内容に関係しているので、ここではわかりません。なぜこのようになるのかは理解できますが、他の人を誤解させるのが心配なので、忘れてください。
- 一般的に、タスク シーケンス に関連する概念はそれほど単純ではなく、ブロッキング、スケジュール(これらの側面については、
C
やJava
などの他のマルチスレッド言語を参照するか、オペレーティング システムの内容を確認することができます。 - 単純な ビジネス実装 であれば、基礎となる多くのことを知る必要はありません。
ここでタスクの処理を開始します:
- Processing
task2
: - Processing
task1
: - 処理
task3
:
わかりました、イベント ループ# # #それでおしまい。 その後、
Javascript エンジンは スリープ フェーズに入ります (Javascript エンジンは終了しません!)、新しいタスクが実行されるのを待ってから、次のイベントを開始しますループ。 備考:
- これは単なる単純な例です
- イベント ループには複数のタスク キューを持つことができます
- タスクシーケンスにはマイクロタスク シーケンスとマクロタスク シーケンスの 2 種類があります。
- 今回のスクリプト コードはマクロタスク シーケンスの 1 つです。
- 最後に: Javascript エンジン
これは私の
精読 Javascript シリーズです3 番目の記事、不意を突かれた イベント ループ 、一度に多くのことを深く掘り下げるようです...しかし、これは最も 不合理なプログラミング配置だと思います。ほとんどのドキュメントでは、タスク シーケンスと コール スタック#が分離されています。 ## ですが、~~_____~~ では、これらは 1 つである必要があり、都合のよい理由で分離してはなりません 。 JavaScript の詳細については、仕様を読むだけでなく、JS エンジン の実装ドキュメントも読むことをお勧めします。一部の高度な内容は仕様には含まれていませんが、これらのドキュメントには含まれています。ドキュメント (Google で検索してください。Baidu でも検索できます)。
JavaScript エンジン に興味がある場合は、次を参照してください:
MDN About_JavascriptChromium V8 リファレンス
- Github V8
- とはいえ、初心者が V8 のソースコードを一気に見るのはあまりお勧めできませんが、頭が割れるような感覚と全身が震える感覚はとても楽しいです。 ……
JavaScript ビデオ チュートリアル
以上がJS の実行コンテキスト、実行スタック、イベント ループを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

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

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

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

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

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

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

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


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

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

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック









