JavaScript をプログラミングするとき、システムを正常に構築するには関数と変数の宣言を避けることはできませんが、インタプリタはこれらの関数と変数をどこでどのように見つけるのでしょうか?これらのオブジェクトを参照すると、正確には何が起こるのでしょうか?
元のリリース: Dmitry A. Soshnikov
公開時期: 2009-06-27
ロシア語のアドレス: http://dmitrysoshnikov.com/ecmascript/ru-chapter-2-variable-object/
英語翻訳: Dmitry A. Soshnikov
リリース時期: 2010-03-15
英語アドレス: http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/
部分的に翻訳が困難
ほとんどの ECMAScript プログラマは、変数が実行コンテキストと密接に関連していることを知っているはずです:
var a = 10 // グローバル コンテキストの変数
(function () {
var b = 20; // グローバル コンテキストのローカル変数function context
})();
alert(a); // 10
alert(b); // グローバル変数 "b" が宣言されていません
多くのプログラマー ご存知のとおり、現在の ECMAScript 仕様では、独立スコープは「関数」コード タイプの実行コンテキストを通じてのみ作成できると規定されています。つまり、C/C と比較して、ECMAScript の for ループはローカル コンテキストを作成できません。
for (var k in {a: 1 , b: 2}) {
alert(k);
}
alert(k); // ループは終了しましたが、変数 k はまだ現在のスコープ内にあります
見てみましょう データを宣言したときに発見した詳細を見てみましょう。
データ宣言
変数が実行コンテキストに関連している場合、変数自体はデータがどこに保存されているか、またそのデータにアクセスする方法を知っている必要があります。この仕組みを変数オブジェクトと呼びます。
変数オブジェクト (VO と略します) は、実行コンテキストに関連する特別なオブジェクトです。
変数 (var、変数宣言);
FunctionDeclaration (FunctionDeclaration と略します); FD);
関数の仮パラメータ
たとえば、通常の ECMAScript オブジェクトを使用して変数オブジェクトを表すことができます:
VO = {};
前述したように、VO は実行コンテキストのプロパティです:
activeExecutionContext = {
VO : {
//コンテキスト データ (var、FD、関数の引数)
}
};
グローバル コンテキスト変数オブジェクトのみが、間接的にアクセスする VO プロパティ名を渡すことができます。 (グローバル コンテキストでは、グローバル オブジェクト自体が変数オブジェクトであるため、後で詳しく説明します)、VO オブジェクトは内部メカニズムの実装にすぎないため、他のコンテキストでは直接アクセスできません。
変数または関数を宣言するとき、VO の新しい属性を作成するときと他に違いはありません (つまり、名前と対応する値があります)。
例:
var a = 10;
function test(x) {
var b = 20;
test(30); 対応する変数オブジェクトは次のとおりです。
コードをコピー
// テスト関数コンテキストの変数オブジェクト
VO(test functionContext) = {
x: 30,
b: 20
};
特定の実装レベル (および仕様) では、変数オブジェクトは単なる抽象的な概念です。 (基本的に、特定の実行コンテキストでは、VO 名が異なり、初期構造も異なります。
異なる実行コンテキストの変数オブジェクト
すべてのタイプの実行コンテキストで、変数オブジェクトの一部の操作 (変数など)この観点から、変数オブジェクトを抽象的な基本的なものとして理解し、関数のコンテキストで変数オブジェクトに関連する追加の内容を定義することも容易になります。 🎜>コードをコピー
コードは次のとおりです:
抽象変数オブジェクト VO (変数初期化プロセスの一般的な動作)
║
╠══> グローバル コンテキスト変数オブジェクト GlobalContextVO
║ (VO === this === global)
║
╚══> 関数コンテキスト変数オブジェクト FunctionContextVO
(VO === AO、および追加された
詳しく見てみましょう:
グローバル コンテキスト内の変数オブジェクト
まず、グローバル オブジェクトを明確に定義する必要があります。
グローバル オブジェクト (グローバル オブジェクト) は、実行コンテキストに入る前に作成されます。
このオブジェクトのコピーは 1 つだけあり、そのプロパティはプログラム内のどこからでもアクセスでき、グローバル オブジェクトのライフサイクルはプログラムが終了した時点で終了します。
コードをコピー
グローバル オブジェクトの最初の作成段階では、Math、String、Date、parseInt が独自の属性として使用され、他の属性も初期化されます。また、他の追加オブジェクトを属性として作成することもできます。グローバル オブジェクト自体を指すこともできます)。たとえば、DOM では、グローバル オブジェクトの window 属性はグローバル オブジェクト自体を参照できます (もちろん、すべての特定の実装がこのようになるわけではありません):
global = {
Math: <...>,
String: <.. .>
...
...
window: global //自身を参照
};
プロパティにアクセスするとき、接頭辞は通常無視されます。グローバル オブジェクトには名前で直接アクセスできないためです。ただし、グローバル コンテキストの this を通じてグローバル オブジェクトにアクセスすることはできますし、それ自体を再帰的に参照することもできます。たとえば、DOM のウィンドウです。要約すると、コードは次のように省略できます:
String( 10); // global.String(10);
// プレフィックス付き
window.a = 10; global.a = 10 ;
this.b = 20; // global.b = 20;
つまり、グローバル コンテキストの変数オブジェクトに戻ります。 object はグローバル オブジェクトそのものです:
VO(globalContext) === global;
この原則に基づいて、対応関係がグローバル コンテキストで宣言されている場合にのみ、この結論を理解することが非常に必要です。グローバル オブジェクトのプロパティを通じて間接的にアクセスします (たとえば、事前に変数名がわからない場合)。
var a = new String('test' );
alert(a); // 直接アクセス、VO(globalContext) で見つかります: "test"
alert(window['a']); // グローバル経由の間接アクセス: global === VO (globalContext) ): "test"
alert(a === this.a); // true
var aKey = 'a';
alert(window[aKey]);動的プロパティ名 アクセス: "test"
関数コンテキストの変数オブジェクト
関数実行コンテキストでは、現時点では VO に直接アクセスできません (アクティベーション オブジェクトによって再生されます)。略してAO) VOの役割。
VO(functionContext) === AO;
アクティブ オブジェクトは関数コンテキストに入るときに作成され、関数の argument 属性を通じて初期化されます。 argument 属性の値は Arguments オブジェクトです:
AO = {
arguments:
};
Arguments オブジェクトは、次の属性を含むアクティブ オブジェクトの属性です。現在の関数への参照
length — 実際に渡されるパラメータの数
properties-indexes (文字列型の整数) プロパティの値は、関数のパラメータ値です (パラメータ内で左から右に配置されます)リスト)。 property-indexes 内の要素の数は、arguments.length と等しくなります。properties-indexes の値は、実際に渡されるパラメータと共有されます。
例:
function foo(x, y, z) {
// 宣言された関数パラメータの引数の数 (x, y, z)
alert(foo.length) // 3
// 実際に渡されるパラメータの数 (x、y のみ)
alert(arguments.length); // 2
// パラメータの呼び出し先は関数自体です
alert(arguments.callee) === foo); // true
// パラメータ共有
alert(x === argument[0]); // true
alert(x); // 10
arguments[ 0] = 20;
alert(x); // 20
x = 30;
alert(arguments[0]); // 30
// ただし、パラメータ z はありません。渡されたパラメータは共有されません
z = 40;
alert(arguments[2]) // 未定義
arguments[2] = 50; / 40
}
foo(10, 20);
コンテキスト コードを処理する 2 つの段階
これで、ようやくこの記事の核心部分に到達しました。実行コンテキストのコードは、次の 2 つの基本的な処理段階に分割されます。
実行コンテキストの開始
コードの実行
変数オブジェクトの変更は、これら 2 つの段階と密接に関連しています。
注: これら 2 つの段階の処理は一般的な動作であり、コンテキストの種類とは関係ありません (つまり、パフォーマンスはグローバル コンテキストと関数コンテキストで同じです)。
実行コンテキストを入力します
実行コンテキストに入るとき (コード実行前)、VO には既に次の属性が含まれています (前述のとおり):
関数のすべての仮パラメータ (関数実行中の場合) context Medium)
- 名前と対応する値で構成される変数オブジェクトのプロパティが作成されます。対応するパラメーターが渡されない場合は、名前と未定義の値で構成される変数オブジェクトのプロパティも作成されます。
すべての関数宣言 (FunctionDeclaration、FD)
- 変数オブジェクトに同じ名前のプロパティが既に存在する場合、名前と対応する値で構成される変数オブジェクトのプロパティ (関数オブジェクト) が作成されます。この属性は完全に置き換えられます。
すべての変数宣言 (var、VariableDeclaration)
- 変数名が宣言された仮パラメータまたは関数と同じである場合、名前と対応する値 (未定義) で構成される変数オブジェクトのプロパティが作成されます。変数宣言は、このタイプの既存のプロパティを妨げません。
例を見てみましょう:
var c = 10;
function d() {}
var e = function _e() {};
(function x() {});
}
test(10); //
a: 10,
b: 未定義,
c : 未定義、
d:
e: 未定義
};
この後、コンテキスト コードの処理の第 2 段階、つまりコードの実行に入ります。
コード実行
このサイクル中、AO/VO はすでに属性を持っています (ただし、すべての属性が値を持っているわけではなく、ほとんどの属性の値はまだシステム デフォルトの初期値である未定義のままです)。
前の例と同様に、AO/VO はコード解釈中に次のように変更されました:
AO['e'] =
もう 1 つの典型的な例:
alert(x); // 関数
var x = 10;
alert(x); // 10
x = 20;
alert(x); // 20
VO['x'] =
// 関数 "x" が宣言されていない場合 // このとき、"x" の値は未定義である必要があります
// ただし、この場合の変数宣言は、同じ名前の関数の値には影響しません
VO['x'] = < ;値は乱れず、機能は維持されます>
次に、コード実行フェーズで、VO は次の変更を行います:
この影響は 2 番目と 3 番目のアラートで確認できます。
以下の例では、変数がコンテキストフェーズ中に VO に入れられることが再度わかります。 (コードの else 部分は決して実行されませんが、とにかく変数 "b" が VO に存在するためです。)
コードをコピー
alert(b); // 未定義、b が宣言されていないのではなく、b の値が未定義である
変数について
通常、JavaScript に関連するさまざまな記事や本はすべて、「(グローバル コンテキストで) var キーワードを使用しても、(どこでも) var キーワードを使用しなくても、変数を宣言できる」と主張しています。これは誤解であることに注意してください。
変数は常に、var キーワードを使用することによってのみ宣言できます。
上記の代入ステートメント:
a = 10;
次の例で具体的な違いを見てみましょう:
コードをコピーします
コードをコピー
コードは次のとおりです:
コードをコピーします
コードは次のとおりです:
コードをコピー
コードは次のとおりです:
a = 10;
alert(window.a); // 10
alert(delete a); // true
alert(window.a); >var b = 20;
alert(window.b); // 20
alert(delete b); // false
alert(window.b); // 여전히 20 >
그러나 이 규칙은 하나의 컨텍스트, 즉 eval 컨텍스트에서는 왜곡될 수 없으며 변수에는 {DontDelete} 속성이 없습니다.
alert(window.a) // 정의되지 않음
이 인스턴스를 테스트할 때 일부 디버깅 도구(예: Firebug) 콘솔을 사용하는 경우 Firebug도 eval을 사용하여 콘솔에서 코드를 실행한다는 점에 유의하세요. 따라서 변수 속성에도 {DontDelete} 속성이 없으므로 삭제가 가능합니다.
특수 구현: __parent__ 속성
예(SpiderMonkey, Rhino):
alert(foo.__parent__); // global VO = foo.__parent__; Alert(VO.a); // 10
alert(VO === global); // true
위의 예에서 foo 함수가 전역에서 생성되는 것을 볼 수 있습니다. 따라서 __parent__ 속성은 전역 컨텍스트의 변수 객체, 즉 전역 객체를 가리킵니다.
그러나 SpiderMonkey에서는 동일한 방식으로 활성 개체에 액세스할 수 없습니다. 다른 버전의 SpiderMonkey에서는 내부 함수의 __parent__가 때때로 null을 가리키기도 하고 때로는 전역 개체를 가리키기도 합니다.
Rhino에서는 동일한 방식으로 활성 개체에 액세스하는 것이 완전히 가능합니다.
예(Rhino):
코드 복사
var AO = (함수 () { }).__parent__;
print(AO.y); // 20
// 현재 활성 객체의 __parent__는 기존 전역 객체입니다.
// 변수 객체의 특수 체인
// 그래서 이를 범위 체인이라고 부릅니다.
print(AO.__parent__ === global); // true
print(AO.__parent__.x) // 10
})() ;
요약
이번 글에서는 실행 컨텍스트와 관련된 객체를 심층적으로 살펴보았습니다. 이 지식이 귀하에게 도움이 되기를 바라며 귀하가 직면한 몇 가지 문제나 혼란을 해결할 수 있기를 바랍니다. 계획대로 다음 장에서는 범위 체인, 식별자 확인 및 클로저를 살펴보겠습니다.
궁금한 점이 있으시면 아래 댓글로 답변해 드리겠습니다.
기타 참고자료
10.1.3 –
변수 인스턴스화
;
10.1.5 –

Object转byte与byte转Object今天实现一下如何从Object去转为byte和如何从byte转为Object。首先,定义一个类student:packagecom.byteToObject;importjava.io.Serializable;publicclassstudentimplementsSerializable{privateintsid;privateStringname;publicintgetSid(){returnsid;}publicvoidsetSid(in

1.Object类介绍Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object的引用进行接收。范例:使用Object接收所有类的对象classPerson{}classStudent{}publicclassTest{publicstaticvoidmain(String[]args){function(newPerson());function(newStudent());}public

对于PHP开发者来说,遇到“Undefinedvariable”警告信息是非常常见的一件事情。这种情况通常出现在尝试使用未定义的变量时,会导致PHP脚本无法正常执行。这篇文章将为大家介绍如何解决“PHPNotice:Undefinedvariable:的解决方法in”的问题。造成问题的原因:在PHP脚本中,如果变量未被初始化或赋值,就会产生“Un

Java使用Object类的getClass()函数获取对象的运行时类在Java中,每个对象都有一个类,这个类定义了对象的属性和方法。我们可以使用getClass()函数来获取对象的运行时类。getClass()函数是Object类的成员函数,因此所有的Java对象都可以调用该函数。本文将介绍getClass()函数的使用方法以及给出一些代码示例。使用get

基本数据类型与Object的关系我知道大家是不是都听说过Object是所有类型的基类,但是这句话其实并不是正确的,因为java中基本数据类型跟Object是没有任何关系的.这里举一个例子这里在进行调用swap方法时,是不能直接将int类型传给swap(Objectobj)方法的,因为Object其实跟基本数据类型没有一点关系,这个时候a就发现我们类型不匹配,所以就自动包装成了Integer类型了,这个时候就能跟Object产生联系了,才能成功调用swap方法了.Object、基本数据类型的包装类

PHPNotice:Tryingtogetpropertyofnon-object解决方法当你在使用PHP进行开发时,你可能会遇到这样的错误提示:“Notice:Tryingtogetpropertyofnon-object。”这个错误提示通常是由于你使用了一个未初始化的对象,或是你的对象在某一段代码中丢失了引用,从而无法正确访问属

PHPNotice:Tryingtogetpropertyofnon-object的解决方法在使用PHP编写代码的过程中,我们可能会遇到“Tryingtogetpropertyofnon-object”的错误提示。这个错误提示通常是由于我们在尝试访问一个不存在的对象属性,导致代码出现了错误。这个错误提示通常会出现在以下情况下:对象不存

Redis的两层数据结构简介redis的性能高的原因之一是它每种数据结构都是经过专门设计的,并都有一种或多种数据结构来支持,依赖这些灵活的数据结构,来提升读取和写入的性能。如果要了解redis的数据结构,可以从两个不同的层面来讨论它:第一个层面,是从使用者的角度,这一层面也是Redis暴露给外部的调用接口,比如:string,list,hash,set,sortedset。第二个层面,是从内部实现的角度,属于更底层的实现,比如:dict,sds,ziplist,quicklist,skiplis


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

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

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

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

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

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

ホットトピック



