ホームページ ウェブフロントエンド jsチュートリアル JavaScript スコープ チェーン パート 3: スコープ チェーンの特性

JavaScript スコープ チェーン パート 3: スコープ チェーンの特性

Dec 20, 2016 pm 04:26 PM
javascript

スコープチェーンと関数 [[scope]] 属性に関連するいくつかの重要な機能を見てみましょう。

クロージャ

ECMAScript では、クロージャは関数の [[scope]] に直接関連しています。前述したように、[[scope]] は関数の作成時に保存され、関数とともに存続し、消滅します。実際、クロージャは関数コードとその [[スコープ]] の組み合わせです。したがって、[[Scope]] には、関数内で作成された字句スコープ (親変数オブジェクト) がオブジェクトの 1 つとして含まれます。関数がさらにアクティブ化されると、変数オブジェクト (作成時に静的に保存される) のこの字句チェーン内で、より上位のスコープの変数が検索されます。例:

var x = 10;
  
function foo() {
  alert(x);
}
  
(function () {
  var x = 20;
  foo(); // 10, but not 20
})();
ログイン後にコピー

関数の作成時に定義された字句スコープを使用して、識別子の解決中に変数が 30 ではなく 10 に解決されることが再度わかります。さらに、この例では、関数 (この場合は関数 "foo" から返された匿名関数) の [[scope]] が、関数によって作成されたスコープが完了した後でも存続することも明確に示しています。

ECMAScript のクロージャ理論とその実行メカニズムの詳細については、後ほど説明します。

コンストラクターを通じて作成された関数の [[scope]]

上の例では、関数の作成時に関数の [[scope]] 属性が取得され、親のすべての変数が取得されることがわかります。コンテキストには、この属性を通じてアクセスできます。ただし、この規則には重要な例外があり、関数コンストラクターを通じて作成された関数がそれに関係します。

var x = 10;
  
function foo() {
  
  var y = 20;
  
  function barFD() { // 函数声明
    alert(x);
    alert(y);
  }
  
  var barFE = function () { // 函数表达式
    alert(x);
    alert(y);
  };
  
  var barFn = Function('alert(x); alert(y);');
  
  barFD(); // 10, 20
  barFE(); // 10, 20
  barFn(); // 10, "y" is not defined
  
}
  
foo();
ログイン後にコピー

関数コンストラクターを通じて作成された関数「bar」が変数「y」にアクセスできないことがわかります。ただし、これは関数 "barFn" に [[scope]] 属性がないという意味ではありません (そうでない場合は変数 "x" にアクセスできません)。問題は、関数コンストラクターを介して作成された関数の [[scope]] 属性が常に唯一のグローバル オブジェクトであることです。これを念頭に置くと、このような関数を使用してグローバル コンテキスト クロージャ以外のトップレベル コンテキスト クロージャを作成することはできません。

二次元スコープ チェーン検索

スコープ チェーンでの検索で最も重要な点は、ECMAScript のプロトタイプ機能から派生した、変数オブジェクト (存在する場合) のプロパティを考慮する必要があることです。プロパティがオブジェクト内で直接見つからない場合、クエリはプロトタイプ チェーンで続行されます。これは、2 次元連鎖検索と呼ばれることがよくあります。 (1) スコープ チェーン リンク、(2) 各スコープ チェーン - プロトタイプ チェーン リンクの奥深くまで進みます。プロパティが Object.prototype で定義されている場合、この効果を確認できます。

function foo() {
  alert(x);
}
  
Object.prototype.x = 10;
  
foo(); // 10
ログイン後にコピー

アクティブ オブジェクトにはプロトタイプがありません。次の例でわかります:

function foo() {
  
  var x = 20;
  
  function bar() {
    alert(x);
  }
  
  bar();
}
  
Object.prototype.x = 10;
  
foo(); // 20
ログイン後にコピー

関数 "bar" コンテキストのアクティブ化オブジェクトにプロトタイプがある場合、"x" は Object.prototype にあるため解決されます。 AO では直接解析されません。しかし、上記の最初の例では、識別子の解決中に、Object.prototype を継承するグローバル オブジェクト (一部の実装では必ずしもそうであるとは限りません) に到達するため、「x」は 10 に解決されます。

同じ状況が、SpiderMokey の一部のバージョンの名前付き関数式 (NFE と略される) でも発生します。特定のオブジェクトには、Object.prototype から継承された関数式のオプションの名前が格納されます。Blackberry バージョンの一部のバージョンでは、実行時間アクティブ化オブジェクトは Object.prototype から継承します。

グローバルおよび eval コンテキストのスコープ チェーン

ここでは必ずしも興味深いものではありませんが、注意が必要です。グローバル コンテキストのスコープ チェーンには、グローバル オブジェクトのみが含まれます。コード eval のコンテキストには、現在の呼び出しコンテキストと同じスコープ チェーンがあります。

globalContext.Scope = [
  Global
];
  
evalContext.Scope === callingContext.Scope;
ログイン後にコピー

コード実行中のスコープ チェーンへの影響

ECMAScript には、コード実行フェーズ中にスコープ チェーンを変更できるステートメントが 2 つあります。これが with ステートメントと catch ステートメントです。これらはスコープ チェーンの先頭に追加され、オブジェクトはこれらの宣言に表示される識別子の中から検索する必要があります。これらのいずれかが発生した場合、スコープ チェーンは次のように簡単に変更されます:

Scope = withObject|catchObject + AO|VO + [[Scope]]
ログイン後にコピー

この例では、オブジェクトがパラメータとして追加されます (プレフィックスなしでこのオブジェクトのプロパティにアクセスできるようになります)。

var foo = {x: 10, y: 20};
  
with (foo) {
  alert(x); // 10
  alert(y); // 20
}
ログイン後にコピー

スコープ チェーンは次のように変更されます:

Scope = foo + AO|VO + [[Scope]]
ログイン後にコピー

with ステートメントを通じて、オブジェクト内の識別子の解決がスコープ チェーンのフロントエンドに追加されることが再度わかります:

var x = 10, y = 10;
  
with ({x: 20}) {
  
  var x = 30, y = 30;
  
  alert(x); // 30
  alert(y); // 30
}
  
alert(x); // 10
alert(y); // 30
ログイン後にコピー

在进入上下文时发生了什么?标识符“x”和“y”已被添加到变量对象中。此外,在代码运行阶段作如下修改:

x = 10, y = 10;

对象{x:20}添加到作用域的前端;

在with内部,遇到了var声明,当然什么也没创建,因为在进入上下文时,所有变量已被解析添加;

在第二步中,仅修改变量“x”,实际上对象中的“x”现在被解析,并添加到作用域链的最前端,“x”为20,变为30;

同样也有变量对象“y”的修改,被解析后其值也相应的由10变为30;

此外,在with声明完成后,它的特定对象从作用域链中移除(已改变的变量“x”--30也从那个对象中移除),即作用域链的结构恢复到with得到加强以前的状态。

在最后两个alert中,当前变量对象的“x”保持同一,“y”的值现在等于30,在with声明运行中已发生改变。

同样,catch语句的异常参数变得可以访问,它创建了只有一个属性的新对象--异常参数名。图示看起来像这样:

try {
  ...
} catch (ex) {
  alert(ex);
}
ログイン後にコピー

作用域链修改为:

var catchObject = {
  ex: <exception object>
};
  
Scope = catchObject + AO|VO + [[Scope]]
ログイン後にコピー

在catch语句完成运行之后,作用域链恢复到以前的状态。

结论

在这个阶段,我们几乎考虑了与执行上下文相关的所有常用概念,以及与它们相关的细节。按照计划--函数对象的详细分析:函数类型(函数声明,函数表达式)和闭包。顺便说一下,在这篇文章中,闭包直接与[[scope]]属性相关,但是,关于它将在合适的篇章中讨论。

 以上就是JavaScript作用域链其三:作用域链特征的内容,更多相关内容请关注PHP中文网(www.php.cn)! 


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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テクノロジー

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 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と 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 で HTTP ステータス コードを簡単に取得する方法 JavaScript で HTTP ステータス コードを簡単に取得する方法 Jan 05, 2024 pm 01:37 PM

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

See all articles