ES5では、変数オブジェクト(VO) がレキシカル環境に変更されました。VO は知覚としてすでに非常に明白であるため、このような変更の動機は何ですか?
2 に答える
変数オブジェクトは環境レコードに似ていると思います。
環境レコードは、関連するレキシカル環境のスコープ内で作成される識別子バインディングを記録します。
ES5 には、2 種類の環境レコードがあります。
宣言型環境レコードは、ECMAScript 言語の構文要素 ( FunctionDeclarations、 VariableDeclarations、および識別子バインディングを ECMAScript 言語値に直接関連付けるCatch句など) の効果を定義するために使用されます。オブジェクト環境レコードは、 ProgramやWithStatementなど、識別子バインディングをオブジェクトのプロパティに関連付けるECMAScript 要素の効果を定義するために使用されます。
したがって、問題は、ES3 変数オブジェクトのようにオブジェクト環境レコードのみを使用する代わりに、宣言型環境レコードが導入された理由です。違いは、宣言的な環境レコードは不変のバインディングを持つことができるということです:
すべての環境レコードでサポートされる可変バインディングに加えて、宣言型環境レコードは不変バインディングも提供します。不変バインディングとは、識別子と値の間の関連付けが確立されると変更できないバインディングです。
不変バインディングには、オブジェクトに直接相当するものはありません。プロパティは、構成不可および書き込み不可の両方として定義でき、不変になります。でも、
不変バインディングの作成と初期化は別個のステップであるため、そのようなバインディングは初期化された状態または初期化されていない状態のいずれかで存在する可能性があります。
ただし、初期化されていないプロパティを持つことはできません。値が定義されていない設定不可能な書き込み不可能なプロパティを定義すると、目的の値に初期化できなくなります。
ES5 で初期化されていない不変のバインディングを持つことは不可能だと思います。CreateImmutableBinding はDeclaration Binding InstantiationとFunction Definitionでのみ使用され、どちらの場合も InitializeImmutableBinding ですぐに初期化されます。
しかし、JavaScript 1.5 のように、初期化されていない不変バインディングを言語の拡張機能として許可するために、これが行われた可能性がありますconst
。あるいは、彼らはすでに ES6 を念頭に置いていたのかもしれませんconst
。
あなたがリンクした ES3 の記事を書いた同じ著者が、ES5 についても書いています (そして、そのセクションをそこにリンクしていました)。ECMA-262-5の「Declarative environment record」セクションから Soshnikov 氏の言葉を詳しく引用します。第 3.2 章。レキシカル環境: ECMAScript の実装:
一般に、宣言型レコードのバインディングは、実装の低レベルで直接格納されると想定されます(たとえば、仮想マシンのレジスタに格納されるため、高速アクセスが提供されます)。これが、ES3 で使用されていた古いアクティベーション オブジェクトの概念との主な違いです。
つまり、仕様では、この場合非効率的な単純なオブジェクトとして宣言型レコードを実装する必要はありません (間接的には推奨しません) 。この事実からの結果は、宣言的な環境レコードがユーザーレベルに直接公開されると想定されていないことです。つまり、レコードのプロパティなどとしてこれらのバインディングにアクセスすることはできません。実際、以前は ES3 でもできませんでした —アクティベーション オブジェクトにユーザーが直接アクセスすることもできませんでした (ただし、Rhino の実装では
__parent__
プロパティを介して公開されていましたが)。宣言型レコードを使用すると、完全なレキシカル アドレス指定手法を使用できる可能性があります。つまり、スコープ チェーンのルックアップを行わずに必要な変数に直接アクセスできます。コンパイル時でも)。ただし、ES5仕様では、この事実について直接言及していません。
繰り返しになりますが、古いアクティベーション オブジェクトの概念を宣言的な環境レコードに置き換える必要があった理由を理解する必要がある主なことは、まず第一に実装の効率性です。
したがって、Brendan Eich も(最後の段落で)言及したように — ES3でのアクティベーション オブジェクトの実装は単なる「バグ」でした。. ES1-3 のスコープに対するオブジェクトの悪用 (これもまた、1995 年に JS でそうし、言語を急いで実装するために必要なオブジェクトを節約したのは私に責任があります) はバグであり、機能ではありませんでした。
これ以上うまく表現できないと思います。