目次
1. グローバル初期化
2. 関数 A を実行します
3. 関数 B を実行します
简单的总结语
ホームページ ウェブフロントエンド jsチュートリアル すべてのプログラマーが知っておくべき、定義から実行までの JavaScript の詳細な紹介

すべてのプログラマーが知っておくべき、定義から実行までの JavaScript の詳細な紹介

Mar 10, 2017 pm 02:43 PM

JavaScript の定義から実行まで、JS エンジンは実装層で多くの初期化作業を実行します。そのため、JS エンジンの動作メカニズムを学ぶ前に、実行環境スタック、グローバル オブジェクトなどの関連する概念をいくつか紹介する必要があります。 、実行環境、変数オブジェクト、アクティブ オブジェクト、スコープとスコープ チェーンなど。これらの概念は、JS エンジンのコア コンポーネントです。この記事の目的は、各概念を個別に説明することではなく、簡単なデモを使用して分析を行い、JS エンジンの定義から実行までの詳細と、その中でこれらの概念が果たす役割を包括的に説明することです。

var x = 1;  //定义一个全局变量 x
function A(y){
   var x = 2;  //定义一个局部变量 x
   function B(z){ //定义一个内部函数 B
       console.log(x+y+z);
   }
   return B; //返回函数B的引用
}
var C = A(1); //执行A,返回B
C(1); //执行函数B
ログイン後にコピー

このデモはクロージャで、実行結果は4です。以下では、グローバル初期化実行関数A実行関数Bの3段階でJSを分析します。エンジンの動作メカニズム:

1. グローバル初期化

JS エンジンが実行可能コードを入力すると、次の 3 つの初期化タスクを完了する必要があります:

まず、グローバル オブジェクト (グローバル オブジェクト) を作成します。グローバルにのみ存在する コピー、そのプロパティはどこからでもアクセスでき、その存在はアプリケーションのライフサイクル全体に伴います。グローバル オブジェクトが作成されると、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)
        }
    }
];
ログイン後にコピー

3. 関数 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对象就存在这个问题,因此我们围绕这个问题可以做很多性能优化的工作,当然还有其他方面的优化,此处不再赘述,本文仅当作抛砖引玉吧!

以上がすべてのプログラマーが知っておくべき、定義から実行までの JavaScript の詳細な紹介の詳細内容です。詳細については、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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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テクノロジー

ディスカスとは何ですか? Discuzの定義と機能紹介 ディスカスとは何ですか? Discuzの定義と機能紹介 Mar 03, 2024 am 10:33 AM

「Discuz の探索: 定義、機能、およびコード例」 インターネットの急速な発展に伴い、コミュニティ フォーラムは人々が情報を取得し、意見を交換するための重要なプラットフォームになりました。多くのコミュニティ フォーラム システムの中でも、Discuz は中国でよく知られたオープン ソース フォーラム ソフトウェアとして、大多数の Web サイト開発者や管理者に好まれています。それで、ディスカスとは何ですか?どのような機能があり、Web サイトにどのように役立つのでしょうか?この記事では、Discuz について詳しく紹介し、読者がDiscuz についてさらに学ぶのに役立つ具体的なコード例を添付します。

MySQL複合主キーの定義と機能 MySQL複合主キーの定義と機能 Mar 15, 2024 pm 05:18 PM

MySQL の複合主キーは、テーブル内の複数のフィールドで構成される主キーを指し、各レコードを一意に識別するために使用されます。単一の主キーとは異なり、複合主キーは複数のフィールドの値を組み合わせて形成されます。テーブルを作成するときに、複数のフィールドを主キーとして指定することにより、複合主キーを定義できます。複合主キーの定義と機能を示すために、最初に users という名前のテーブルを作成します。このテーブルには、id、ユーザー名、電子メールの 3 つのフィールドが含まれます。id は自動インクリメントされる主キー、ユーザーです。

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

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

PHP インターフェースの概要とその定義方法 PHP インターフェースの概要とその定義方法 Mar 23, 2024 am 09:00 AM

PHP インターフェースの概要とその定義方法 PHP は、Web 開発で広く使用されているオープンソースのスクリプト言語であり、柔軟性があり、シンプルで強力です。 PHP では、インターフェイスは複数のクラス間で共通のメソッドを定義し、ポリモーフィズムを実現し、コードをより柔軟で再利用可能にするツールです。この記事では、PHP インターフェイスの概念とその定義方法を紹介し、その使用法を示す具体的なコード例を示します。 1. PHP インターフェイスの概念 インターフェイスはオブジェクト指向プログラミングにおいて重要な役割を果たし、クラス アプリケーションを定義します。

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

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

全角文字の定義と使用 全角文字の定義と使用 Mar 25, 2024 pm 03:33 PM

全角文字とは何ですか?コンピュータ エンコード システムでは、全幅文字は 2 つの標準文字位置を占める文字エンコード方法です。これに対応して、標準の文字位置を占める文字エンコード方式を半角文字と呼びます。全角文字は通常、中国語、日本語、韓国語、その他のアジアの文字の入力、表示、印刷に使用されます。中国語の入力方法やテキスト編集では、全角文字と半角文字の使用シーンが異なります。全角文字の使用 中国語の入力方法: 中国語の入力方法では、通常、漢字や記号などの中国語の文字を入力するために全角文字が使用されます。

See all articles