ECMAscript 5:オブジェクトとプロパティ

ECMAScript 5は独自の方法で機能します。 ECMAScript 3.1に絞り込まれたECMAScript 4の灰から復活しました。これは後にECMAScript 5( 詳細 )と呼ばれ、愛されるECMAScript 3に基づいて構築された新しい機能層を備えています。



仕様に含まれるいくつかの新しいAPIを発表しましたが、最も興味深い機能はオブジェクトとプロパティのコードにあります。 この新しいコードにより、ユーザーがオブジェクトを操作する方法に大きな影響を与えることができ、ゲッターとセッターを提供し、リスト、操作、または削除を防ぎ、さらに新しいプロパティの追加を防ぐことができます。 要するに、JavaScriptを使用して(他のものを一切使用せずに)既存のJavaScript API(DOMなど)のセットを複製および拡張できます。



非常に良いニュース:これらの機能は、すべての主要なブラウザーに表示されるはずです。 すべての主要なブラウザベンダーがこの仕様に取り組み、製品に実装することに同意しています。 正確な日付はまだ明確ではありませんが、早期に実装される可能性は高くなります。



どうやら、今日のES5の完全な実装はありませんが、いくつかのプロジェクトが既に実装のプロセスにあります。 同時に、 ECMAScript 5仕様 (PDF-この記事では107〜109ページについて説明します)を読むか、GoogleでECMAScriptチームの最新の議論を見ることができます。

注:これらのメソッドの簡単なサンプル実装をいくつか示して、それらがどのように機能するかを説明します。 それらのほとんどすべてが、正しい操作のために他の新しい方法を必要とします-そして、それらは仕様100%に従って実装されていません(たとえば、エラーチェックはありません)。


オブジェクト



ECMAScript 5の新機能-オブジェクトの拡張性を切り替えることができるようになりました。 拡張性を無効にすると、オブジェクトに新しいプロパティを追加できなくなります。



ES5は、オブジェクトの拡張性を操作および検証する2つの方法を提供します。



Object.preventExtensions(obj)、Object.isExtensible(obj)


preventExtensions



はオブジェクトをブロックし、将来の新しいオブジェクトプロパティの作成を防ぎます。 isExtensible



オブジェクトが現在展開中かどうかを判断する機能。



使用例:

var obj = {};

obj.name = "John" ;

print( obj.name );

// John



print( Object.isExtensible( obj ) );

// true



Object.preventExtensions( obj );



obj.url = "http://ejohn.org/" ; // Exception in strict mode



print( Object.isExtensible( obj ) );

// false




* This source code was highlighted with Source Code Highlighter .






プロパティと記述子



プロパティは完全に改訂されました。 それらはオブジェクトに関連付けられた単純な意味ではなくなりました。あなたは今、それらがどのように動作するかを完全に制御できます。 ただし、強度が高いほど、複雑さが増します。



オブジェクトのプロパティは2つの部分に分かれています。



プロパティのコンテンツは2つの方法で定義できます:値(プロパティデータはECMAScript 3で私たちが知っている、愛する伝統的なプロパティです)またはゲッターとセッター(プロパティは「アクセサー」です-WebKitなどのいくつかの最新ブラウザーから知っています)とヤモリ。



さらに、プロパティは...



合計すると、これらのさまざまな属性がプロパティ記述子を構成します。 たとえば、単純な記述子は次のようになります。

{

value: "test" ,

writable: true ,

enumerable: true ,

configurable: true

}




* This source code was highlighted with Source Code Highlighter .






3つの属性(書き込み可能、​​列挙可能、構成可能)はオプションであり、すべてデフォルトでtrueです。 したがって、プロパティの場合は、値、またはゲッターとセッターのいずれかのみを提供する必要があります。



新しいObject.getOwnPropertyDescriptor



メソッドを使用して、既存のObject.getOwnPropertyDescriptor



プロパティに関するこの情報を取得できます。



Object.getOwnPropertyDescriptor(obj、prop)


このメソッドは、プロパティ記述子へのアクセスを許可します。 これは、この情報を取得する唯一の方法です(言い換えると、記述子はユーザーの自由ではありません。記述子はプロパティの可視属性として存在せず、ECMAScriptエンジンに内部的に保存されます)。



使用例:

var obj = { foo: "test" };

print(JSON.stringify(

Object.getOwnPropertyDescriptor( obj, "foo" )

));

// {"value": "test", "writable": true,

// "enumerable": true, "configurable":true}



* This source code was highlighted with Source Code Highlighter .








メソッドObject.defineProperty(obj、prop、desc)


このメソッドを使用すると、オブジェクトの新しいプロパティを定義(または既存のプロパティのハンドルを変更)できます。 このメソッドはプロパティ記述子を取得し、それを使用してプロパティを初期化(または更新)します。



使用例:

var obj = {};

Object.defineProperty( obj, "value" , {

value: true ,

writable: false ,

enumerable: true ,

configurable: true

});



( function (){

var name = "John" ;



Object.defineProperty( obj, "name" , {

get: function (){ return name; },

set: function (value){ name = value; }

});

})();



print( obj.value )

// true



print( obj.name );

// John



obj.name = "Ted" ;

print( obj.name );

// Ted



for ( var prop in obj ) {

print( prop );

}

// value

// name



obj.value = false ; // Exception if in strict mode



Object.defineProperty( obj, "value" , {

writable: true ,

configurable: false

});



obj.value = false ;

print( obj.value );

// false



delete obj.value; // Exception




* This source code was highlighted with Source Code Highlighter .








Object.definePropertyは、ECMAScriptの新しいバージョンの基本メソッドです。 実質的に他のすべての重要な機能は、このメソッドの存在に依存しています。



Object.defineProperties(obj、props)


(それぞれを個別に定義する代わりに)オブジェクトのプロパティを一度にいくつか定義します。



サンプル実装:

Object.defineProperties = function ( obj, props ) {

for ( var prop in props ) {

Object.defineProperty( obj, prop, props[prop] );

}

};




* This source code was highlighted with Source Code Highlighter .








使用例:

var obj = {};

Object.defineProperties(obj, {

"value" : {

value: true ,

writable: false

},

"name" : {

value: "John" ,

writable: false

}

});




* This source code was highlighted with Source Code Highlighter .






プロパティ記述子(および関連するメソッド)は、おそらくECMAScript 5の最も重要な新機能です。これにより、開発者はオブジェクトを非常に正確に制御し、不要な変更を防ぎ、単一のWeb互換APIをサポートできます。



新機能





上記の拡張機能を使用して、いくつかの興味深い新機能が言語に導入されました。



次の2つのメソッドは、オブジェクトのすべてのプロパティの配列を収集するのに非常に役立ちます。



Object.keys(obj)


オブジェクトのすべての列挙プロパティの名前を表す文字列の配列を返します。 その動作は、Prototype.jsライブラリのメソッドの動作と一致します。



サンプル実装:

Object.keys = function ( obj ) {

var array = new Array();

for ( var prop in obj ) {

array.push( prop );

}

return array;

};




* This source code was highlighted with Source Code Highlighter .








使用例:

var obj = { name: "John" , url: "http://ejohn.org/" };

print( Object.keys(obj).join( ", " ) );

// name, url





* This source code was highlighted with Source Code Highlighter .








Object.getOwnPropertyNames(obj)


Object.keysとほぼ同じですが、列挙されたものだけでなく、オブジェクトのすべてのプロパティの名前を返します。



列挙できないプロパティはリストできないため、ECMAScript 3で実装例を行うことはできません。 戻り値と使用法はObject.keysと同じです。



Object.create(プロト、プロップ)


プロトタイプがプロトであり、プロパティがObject.defineProperties(props)を使用して設定される新しいオブジェクトを作成します。



簡単な実装は次のようになります(新しいObject.definePropertiesメソッドが必要です)。

Object.create = function ( proto, props ) {

var obj = new Object();

obj.__proto__ = proto;

if ( typeof props !== "undefined" ) {

Object.defineProperties( obj, props );

}



return obj;

};




* This source code was highlighted with Source Code Highlighter .








注:上記のコードは、Mozilla固有の_proto_プロパティを使用しています。 このプロパティを使用すると、オブジェクトの内部プロトタイプにアクセスできます。また、その値を設定できます。 ES5では、Object.getPrototypeOfメソッドを使用してこのプロパティにアクセスできますが、インストールはできません。したがって、上記のメソッドはESと互換性のある一般的な方法では実装できません。



以前Object.getPrototypeOfについて説明したため、ここでは再度説明しません。


使用例:

function User(){}

User.prototype.name = "Anonymous" ;

User.prototype.url = "http://google.com/" ;

var john = Object.create( new User(), {

name: { value: "John" , writable: false },

url: { value: "http://google.com/" }

});



print( john.name );

// John



john.name = "Ted" ; // Exception if in strict mode




* This source code was highlighted with Source Code Highlighter .








Object.seal(obj)、Object.isSealed(obj)


オブジェクトを封印すると、コードがオブジェクトのプロパティの記述子を削除または変更できなくなり、新しいプロパティが追加されなくなります。



実装例:

Object.seal = function ( obj ) {

var props = Object.getOwnPropertyNames( obj );



for ( var i = 0; i < props.length; i++ ) {

var desc = Object.getOwnPropertyDescriptor( obj, props[i] );



desc.configurable = false ;

Object.defineProperty( obj, props[i], desc );

}



return Object.preventExtensions( obj );

};




* This source code was highlighted with Source Code Highlighter .








既存のプロパティのセットをそのまま残し、新しい追加を提供せずに、同時にユーザーが値を編集できるようにする場合は、オブジェクトをシールすることをお勧めします。



Object.freeze(obj)、Object.isFrozen(obj)


オブジェクトのフリーズはシーリングとほぼ同じですが、プロパティが変更されないという追加があります。



実装例:

Object.freeze = function ( obj ) {

var props = Object.getOwnPropertyNames( obj );



for ( var i = 0; i < props.length; i++ ) {

var desc = Object.getOwnPropertyDescriptor( obj, props[i] );



if ( "value" in desc ) {

desc.writable = false ;

}



desc.configurable = false ;

Object.defineProperty( obj, props[i], desc );

}



return Object.preventExtensions( obj );

};




* This source code was highlighted with Source Code Highlighter .








オブジェクトの凍結は、ロックの究極の形です。 オブジェクトを凍結した後は、解凍することはできません。どのような形でも変更することはできません。 これは、オブジェクトを無期限に正確に残したままにするための最良の方法です。



合わせて、これらの変更は非常に興味深いものであり、作成するオブジェクトを前例のないレベルで制御できます。 優れた点は、これらの機能を使用して、純粋なECMAScriptでより大きく複雑な関数を作成できることです(新しいDOMモジュールの構築、ほとんどのブラウザーAPIの純粋なJavaScriptへの移動など)。 また、すべてのブラウザにはJavaScriptが搭載されているため、これが絶対に楽しみです。



-翻訳者注:記述子は記述子として翻訳されますが、記述子として翻訳することもできます。 ゲッターとセッターには、ロシア語で同じ短くて容量のある定義(値の受信者と値のインストーラー)がないため、専門用語のゲッターとセッターが使用されます。



All Articles