JavaScript の定義から実行まで、JS エンジンは実装層で多くの初期化作業を実行します。そのため、JS エンジンの動作メカニズムを学ぶ前に、実行環境スタック、グローバル オブジェクト、実行といったいくつかの関連概念を導入する必要があります。環境、変数オブジェクト、アクティビティ オブジェクト、スコープ、スコープ チェーンなど、これらの概念は JS エンジンのコア コンポーネントです。この記事の目的は、各概念を個別に説明することではなく、簡単なデモを使用して分析を行い、JS エンジンの定義から実行までの詳細と、その中でこれらの概念が果たす役割を包括的に説明することです。
var x = 1; //定义一个全局变量 xfunction A(y){ var x = 2; //定义一个局部变量 x function B(z){ //定义一个内部函数 B console.log(x+y+z); } return B; //返回函数B的引用}var C = A(1); //执行A,返回BC(1); //执行函数B
このデモはクロージャであり、実行結果は 4 です。以下では、グローバル初期化、実行関数 A、実行関数 Bの 3 つの段階で JS エンジンの動作メカニズムを分析します。
1. グローバル初期化
JS エンジンが実行可能コードを入力すると、次の 3 つの初期化タスクを完了する必要があります:
まず、グローバル オブジェクト (グローバル オブジェクト) のコピーを 1 つだけ作成します。このオブジェクトはグローバルに存在し、プロパティはどこからでもアクセスでき、アプリケーションの存続期間中ずっと存在します。グローバル オブジェクトが作成されると、Math、String、Date、document などの一般的に使用される JS オブジェクトがその属性として使用されます。このグローバル オブジェクトには名前で直接アクセスできないため、別の属性 window があり、window 自体がポイントされているため、window を通じてグローバル オブジェクトにアクセスできます。疑似コードでシミュレートされたグローバル オブジェクトの一般的な構造は次のとおりです。
//创建一个全局对象var globalObject = { Math:{}, String:{}, Date:{}, document:{}, //DOM操作 ... window:this //让window属性指向了自身}
次に、JS エンジンは実行環境スタック (実行コンテキスト スタック) を構築する必要があります。同時に、グローバルも作成する必要があります。実行環境 (実行コンテキスト) EC を作成し、このグローバル実行環境 EC を実行環境スタックにプッシュします。実行環境スタックの機能は、プログラムが正しい順序で実行できるようにすることです。 JavaScript では、関数ごとに独自の実行環境があり、関数が実行されると、その関数の実行環境が実行環境スタックの先頭にプッシュされ、実行権限が取得されます。関数の実行が完了すると、その実行環境はスタックの最上位から削除され、実行権限は前の実行環境に戻ります。疑似コードを使用して、実行環境スタックと EC の間の関係をシミュレートします。
var ECStack = []; //定义一个执行环境栈,类似于数组var EC = {}; //创建一个执行空间,//ECMA-262规范并没有对EC的数据结构做明确的定义,你可以理解为在内存中分配的一块空间ECStack.push(EC); //进入函数,压入执行环境ECStack.pop(EC); //函数返回后,删除执行环境
最後に、JS エンジンは EC に関連付けられたグローバル変数オブジェクト (Varibale オブジェクト) VO も作成し、VO をグローバル オブジェクトにポイントします。 VO には、グローバル オブジェクトの元のプロパティだけでなく、グローバルに定義された変数 x と関数 A も含まれます。同時に、関数 A を定義するときに、内部属性スコープが A に追加され、スコープは VO を指します。各関数が定義されると、それに関連付けられたスコープ属性が作成され、スコープは常に関数が定義されている環境を指します。このときの ECStack の構造は以下の通りです:
ECStack = [ //执行环境栈 EC(G) = { //全局执行环境 VO(G):{ //定义全局变量对象 ... //包含全局对象原有的属性 x = 1; //定义变量x A = function(){...}; //定义函数A A[[scope]] = this; //定义A的scope,并赋值为VO本身 } } ];
2. 関数 A を実行します
実行が A(1) に入ると、JS エンジンは次の作業を完了する必要があります:
まず、JS エンジンは関数 A EC の実行環境を作成すると、EC が実行環境スタックの最上位にプッシュされ、実行権限を取得します。このとき、実行環境スタックには、グローバル実行環境と関数 A の実行環境の 2 つの実行環境が存在します。スタックの最上位に A の実行環境、最下位にグローバル実行環境があります。スタックの。次に、関数 A のスコープ チェーン (Scope Chain) を作成します。JavaScript では、実行環境ごとに識別子解決用のスコープ チェーンがあり、実行環境の作成時にそのスコープ チェーンに含まれるオブジェクトが初期化されます。現在実行中の関数の。
次に、JS エンジンは現在の関数の Activation オブジェクト (Activation Object) AO を作成します。ここでのアクティビティ オブジェクトは変数オブジェクトの役割を果たしますが、その名前は関数内で異なります (変数オブジェクトと考えることができます)。一般的な概念として、アクティブなオブジェクトはそのブランチです)、AO には関数の仮パラメータ、引数オブジェクト、このオブジェクト、およびローカル変数と内部関数の定義が含まれており、AO が先頭にプッシュされます。スコープチェーンの。関数 B を定義するときに、JS エンジンはスコープ属性も B に追加し、そのスコープが関数 B が定義されている環境を指すことに注意してください。関数 B が定義されている環境は、A のアクティブ オブジェクト AO です。 . AO はリンク リストのフロントエンドに位置します。リンク リストはエンドツーエンドで接続されているため、関数 B のスコープは A のスコープ チェーン全体を指します。 この時点での ECStack 構造を見てみましょう:
ECStack = [ //执行环境栈 EC(A) = { //A的执行环境 [scope]:VO(G), //VO是全局变量对象 AO(A) : { //创建函数A的活动对象 y:1, x:2, //定义局部变量x B:function(){...}, //定义函数B B[[scope]] = this; //this指代AO本身,而AO位于scopeChain的顶端,因此B[[scope]]指向整个作用域链 arguments:[],//平时我们在函数中访问的arguments就是AO中的arguments this:window //函数中的this指向调用者window对象 }, scopeChain:<AO(A),A[[scope]]> //链表初始化为A[[scope]],然后再把AO加入该作用域链的顶端,此时A的作用域链:AO(A)->VO(G) }, EC(G) = { //全局执行环境 VO(G):{ //创建全局变量对象 ... //包含全局对象原有的属性 x = 1; //定义变量x A = function(){...}; //定义函数A A[[scope]] = this; //定义A的scope,A[[scope]] == VO(G) } } ];
三、 执行函数B
函数A被执行以后,返回了B的引用,并赋值给了变量C,执行 C(1) 就相当于执行B(1),JS引擎需要完成以下工作:
首先,还和上面一样,创建函数B的执行环境EC,然后EC推入执行环境栈的顶部并获取执行权。 此时执行环境栈中有两个执行环境,分别是全局执行环境和函数B的执行环境,B的执行环境在栈顶,全局执行环境在栈的底部。(注意:当函数A返回后,A的执行环境就会从栈中被删除,只留下全局执行环境)然后,创建函数B的作用域链,并初始化为函数B的scope所包含的对象,即包含了A的作用域链。最后,创建函数B的活动对象AO,并将B的形参z, arguments对象 和 this对象作为AO的属性。此时ECStack将会变成这样:ECStack = [ //执行环境栈
EC(B) = { //创建B的执行环境,并处于作用域链的顶端 [scope]:AO(A), //指向函数A的作用域链,AO(A)->VO(G) var AO(B) = { //创建函数B的活动对象 z:1, arguments:[], this:window } scopeChain:<AO(B),B[[scope]]> //链表初始化为B[[scope]],再将AO(B)加入链表表头,此时B的作用域链:AO(B)->AO(A)-VO(G) }, EC(A), //A的执行环境已经从栈顶被删除, EC(G) = { //全局执行环境 VO:{ //定义全局变量对象 ... //包含全局对象原有的属性 x = 1; //定义变量x A = function(){...}; //定义函数A A[[scope]] = this; //定义A的scope,A[[scope]] == VO(G) } } ];
当函数B执行“x+y+z”时,需要对x、y、z 三个标识符进行一一解析,解析过程遵守变量查找规则:先查找自己的活动对象中是否存在该属性,如果存在,则停止查找并返回;如果不存在,继续沿着其作用域链从顶端依次查找,直到找到为止,如果整个作用域链上都未找到该变量,则返回“undefined”。从上面的分析可以看出函数B的作用域链是这样的:
AO(B)->AO(A)->VO(G)
因此,变量x会在AO(A)中被找到,而不会查找VO(G)中的x,变量y也会在AO(A)中被找到,变量z 在自身的AO(B)中就找到了。所以执行结果:2+1+1=4.
简单的总结语
了解了JS引擎的工作机制之后,我们不能只停留在理解概念的层面,而要将其作为基础工具,用以优化和改善我们在实际工作中的代码,提高执行效率,产生实际价值才是我们的真正目的。就拿变量查找机制来说,如果你的代码嵌套很深,每引用一次全局变量,JS引擎就要查找整个作用域链,比如处于作用域链的最底端window和document对象就存在这个问题,因此我们围绕这个问题可以做很多性能优化的工作,当然还有其他方面的优化,此处不再赘述,本文仅当作抛砖引玉吧!

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

Pythonはデータサイエンスや機械学習により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、簡潔な構文とリッチライブラリエコシステムで知られており、データ分析とWeb開発に適しています。 2。JavaScriptは、フロントエンド開発の中核です。 node.jsはサーバー側のプログラミングをサポートしており、フルスタック開発に適しています。

JavaScriptは、最新のブラウザにすでに組み込まれているため、インストールを必要としません。開始するには、テキストエディターとブラウザのみが必要です。 1)ブラウザ環境では、タグを介してHTMLファイルを埋め込んで実行します。 2)node.js環境では、node.jsをダウンロードしてインストールした後、コマンドラインを介してJavaScriptファイルを実行します。

Quartzタイマーを使用してタスクをスケジュールする場合、Quartzでタスク通知を事前に送信する方法、タスクの実行時間はCron式によって設定されます。今...


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

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

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。
