«前の日記(2008年01月19日) 最新 次の日記(2008年01月21日)» 編集

ema log


2008年01月20日 ECMA-262 の 4章 を読む [長年日記]

_ [JavaScript][Programming] ECMA-262 の 4章 を読む

prototype と __proto__ と constructor に続きがあります。

以下は、「仕様書 ECMA-262 の原文の引用、邦訳の引用、ema のコメント」で構成されています。邦訳は

訳は一応完了しましたが、やっつけ仕事で訳者本人も意味不明の部分が多々あります。そんなわけでこの訳を鵜呑みにするのは勘弁してください。

[Under Translation of ECMA-262 3rd Editionより引用]

と有りますが、この範囲内では僕の英語力では間違いだと感じる部分はなかったので引用しています*1

仕様書部分は、冗長に感じるかもしれませんが、ソースを明示したいので。

まとめとしては

  • オブジェクト は、プロパティ の集合体
  • プロパティは、他のオブジェクトや プリミティブ値 、メソッド を保持するコンテナ
  • コンストラクタは初期化をする関数、かつ、オブジェクト
  • prototype chain
  • prototype chain では、コンストラクタ自体は探索されない
    • コンストラクタとそのプロトタイプは別オブジェクトなので

という内容になっています。

「クラス」という単語は誤解を招きやすいので、意図的に避けています。メソッド呼び出しと this の関係を書いてから、クラスのエミュレーションについて触れます。

ECMAScript4 になると、クラスが導入されるらしいです。AS3 にも有りますね。


ECMA-262 の 4章を読むのが一番分かりやすそう

The following is an informal overview of ECMAScript -- not all parts of the language are described. This overview is not part of the standard proper.

[ECMA-262より引用]

下記は ECMAScript の非公式な概要である -- 言語のすべての部分が記述されるわけではない。この概要は厳密には標準の一部ではない。

[4.2 言語の概要 (Language Overview)より引用]

非公式だとありますが、4章を読むのが一番分かりやすそうです。


オブジェクト は、序列のない プロパティ の集合体

ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects. An ECMAScript object is an unordered collection of properties each with zero or more attributes that determine how each property can be used

[ECMA-262より引用]

ECMAScript はオブジェクトベースである: 基礎的な言語およびホスト設備はオブジェクトによって提供される。また、 ECMAScript プログラムは、通信するオブジェクトの群である。 ECMAScript オブジェクト は、序列のない プロパティ の集合体で、それぞれのプロパティが、その利用されうる方法を決定する 0 個以上の 属性 を持つ

[4.2 言語の概要 (Language Overview)より引用]

プロパティ (properties) の属性 (attributes) は置いておいて、「ECMAScript オブジェクト は、序列のない プロパティ の集合体」という部分が重要です。多言語になれている方には Hash だというイメージを持つのが良いと思います*2。詳細は「8.6 Object 型 (Object type)」を参照。


プロパティとは

Properties are containers that hold other objects, primitive values, or methods.

[ECMA-262より引用]

プロパティは、他のオブジェクトや プリミティブ値 、メソッド を保持するコンテナである。

[4.2 言語の概要 (Language Overview)より引用]

メソッドが特別扱いされています(ちょっと重要)。後、細かい点ですが、

A primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String; an object is a member of the remaining built-in type Object; and a method is a function associated with an object via a property.

[4.2 言語の概要 (Language Overview)より引用]

プリミティブな値は、次の組み込み 型: Undefined, Null, Boolean, Number, String の内のひとつの仲間である; オブジェクトは残りの組み込み 型 Object の仲間である; メソッドはプロパティ経由でオブジェクトに関連づけられた関数である。

[4.2 言語の概要 (Language Overview)より引用]

プリミティブなのは「Undefined, Null, Boolean, Number, and String」ですから、配列はプリミティブではありません。つまり、[ ](Array 初期化子)は、Array コンストラクタでオブジェクトを生成するためのシンタックスシュガーだといえます。C とは異なりますので注意してください。Function も Object ですが、スコープがあったり、this があったりするので特別扱いされています(厳密なのは置いておきます。より詳しくは、「15 ネイティブ ECMAScript オブジェクト (Native ECMAScript Objects)」を参照)。


オブジェクト指向の枠組み

クラスは存在しない

ECMAScript does not contain proper classes such as those in C++, Smalltalk, or Java, but rather, supports constructors which create objects by executing code that allocates storage for the objects and initialises all or part of them by assigning initial values to their properties.

[ECMA-262より引用]

ECMAScript は、C++、Smalltalk あるいは Java のような厳密なクラスを持たない。だが、コードの実行によりオブジェクトを生成するコンストラクタをサポートし、このコードはオブジェクトに記憶領域を確保し、オブジェクトの全て又は一部をプロパティへの初期値代入によって初期化する。

[4.2.1 オブジェクト (Objects)より引用]

現行のJavaScript にクラスはありません。しかし、「オブジェクトを初期化するためのコンストラクタ」と「プロトタイプベースの継承」が存在します。

なお、推測ですが、オブジェクトを new したときには

  1. オブジェクトのためのメモリが確保される
  2. コンストラクタが呼ばれる(this に新しいオブジェクト)

という手続きがおきると思われます。C++ のコンストラクタに非常によく似ています。


prototype

All constructors are objects, but not all objects are constructors. Each constructor has a Prototype property that is used to implement prototype-based inheritance and shared properties. Objects are created by using constructors in new expressions;

[ECMA-262より引用]

コンストラクタは全てオブジェクトであるが、しかし、すべてのオブジェクトがコンストラクタということではない。コンストラクタはそれぞれ prototype プロパティを持ち、プロトタイプベースの継承および共有プロパティの実装に使用される。オブジェクトは new 式中でのコンストラクタ使用により生成される;

[4.2.1 オブジェクト (Objects)より引用]

コンストラクタはオブジェクトです。また、全てのオブジェクトは prototype というプロパティを持ちます*3

Every constructor has an associated prototype, and every object created by that constructor has an implicit reference to the prototype (called the object’s prototype) associated with its constructor.

[ECMA-262より引用]

コンストラクタは皆関連づけられたプロトタイプを持ち、また、そのコンストラクタに作成されたオブジェクトは皆、そのコンストラクタに関連づけられたプロトタイプ (オブジェクトのプロトタイプと呼ばれる) に暗黙の参照がある。

[4.2.1 オブジェクト (Objects)より引用]


「コンストラクタ」と「コンストラクタの prototype の中身」は別々のオブジェクト

「コンストラクタ」と「コンストラクタの prototype の中身」は別々のオブジェクトであることが重要です。このことを忘れるとはまります。すなわち、以上のようになります。


prototype chain

All objects that do not directly contain a particular property that their prototype contains share that property and its value. (snip) In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.

[ECMA-262より引用]

プロトタイプが持つプロパティを直に持たないオブジェクトはすべて、プロパティとその値を共有する。(中略)言いかえれば、まず直接指定されたオブジェクトが、そのプロパティの有無を検査される; そのオブジェクトが指定されたプロパティを持つ場合、それが参照するプロパティである; そのオブジェクトが指定のプロパティを持たない場合、そのオブジェクトのプロトタイプが次に検査される; 以下同様に続く。

[4.2.1 オブジェクト (Objects)より引用]

ECMAScript3 では、プロパティを探す場合に

  1. オブジェクト自身のプロパティ
  2. ... 以下略

という順番で、プロパティが探索されます。

このことが「prototype chain」と呼ばれます。このとき、コンストラクタ自体は探索対象にはなりません。たとえば、Array から作られたオブジェクト全体にメソッドを追加したければ、のように、prototype にメソッドを追加する必要があります。実際の処理はもう少しややこしいのできちんと調べます*4

prototype と __proto__ と constructor に続きがあります。


References
ECMA-262
ECMA-262 邦訳
Kanasan.JS JavaScript 第5版読書会 #2 雑感 [blanket sky]
プロトタイプチェーンの図とか [いげ太のブログ]

*1 日本語変えたい部分は兎も角w

*2 「メソッド呼び出し」と「prototype chain」をもつ Hash と言って間違いないと思う

*3 prototype プロパティ自身は mutable です

*4 また、prototype や constructor は上書き可能なので、下手に上書きするとややこしいことになります。この辺は、まだきちんと分かってないので次回以降に