この翻訳は不完全です。英語から この記事を翻訳 してください。
このページでは、Object.defineProperty()
の追加の使用例を提供します。
プロパティ記述子オブジェクトの代わりにバイナリフラグを使用する
Object.defineProperty()
メソッドを通して多くのプロパティを定義する必要がある場合、各プロパティに対して同じ記述子オブジェクトを使用し、binary flags を通して随時それを再定義してください。
var oDesc = {}; function setProp (nMask, oObj, sKey, vVal_fGet, fSet) { if (nMask & 8) { // accessor descriptor if (vVal_fGet) { oDesc.get = vVal_fGet; } else { delete oDesc.get; } if (fSet) { oDesc.set = fSet; } else { delete oDesc.set; } delete oDesc.value; delete oDesc.writable; } else { // data descriptor if (arguments.length > 3) { oDesc.value = vVal_fGet; } else { delete oDesc.value; } oDesc.writable = Boolean(nMask & 4); delete oDesc.get; delete oDesc.set; } oDesc.enumerable = Boolean(nMask & 1); oDesc.configurable = Boolean(nMask & 2); Object.defineProperty(oObj, sKey, oDesc); return oObj; } /* * :: function setProp :: * * nMask is a bitmask: * flag 0x1: property is enumerable, * flag 0x2: property is configurable, * flag 0x4: property is writable, * flag 0x8: property is accessor descriptor. * oObj is the object on which to define the property; * sKey is the name of the property to be defined or modified; * vVal_fGet is the value to assign to a data descriptor or the getter function * to assign to an accessor descriptor (depending on the bitmask); * fSet is the setter function to assign to an accessor descriptor; * * Bitmask possible values: * * 0 : readonly data descriptor - not configurable, not enumerable (0000). * 1 : readonly data descriptor - not configurable, enumerable (0001). * 2 : readonly data descriptor - configurable, not enumerable (0010). * 3 : readonly data descriptor - configurable, enumerable (0011). * 4 : writable data descriptor - not configurable, not enumerable (0100). * 5 : writable data descriptor - not configurable, enumerable (0101). * 6 : writable data descriptor - configurable, not enumerable (0110). * 7 : writable data descriptor - configurable, enumerable (0111). * 8 : accessor descriptor - not configurable, not enumerable (1000). * 9 : accessor descriptor - not configurable, enumerable (1001). * 10 : accessor descriptor - configurable, not enumerable (1010). * 11 : accessor descriptor - configurable, enumerable (1011). * * Note: If the flag 0x8 is setted to "accessor descriptor" the flag 0x4 (writable) * will be ignored. If not, the fSet argument will be ignored. */ // creating a new empty object var myObj = {}; // adding a writable data descriptor - not configurable, not enumerable setProp(4, myObj, 'myNumber', 25); // adding a readonly data descriptor - not configurable, enumerable setProp(1, myObj, 'myString', 'Hello world!'); // adding an accessor descriptor - not configurable, enumerable setProp(9, myObj, 'myArray', function() { for (var iBit = 0, iFlag = 1, aBoolArr = [false]; iFlag < this.myNumber + 1 || (this.myNumber & iFlag); iFlag = iFlag << 1 ) { aBoolArr[iBit++] = Boolean(this.myNumber & iFlag); } return aBoolArr; }, function(aNewMask) { for (var nNew = 0, iBit = 0; iBit < aNewMask.length; iBit++) { nNew |= Boolean(aNewMask[iBit]) << iBit; } this.myNumber = nNew; }); // adding a writable data descriptor (undefined value) - configurable, enumerable setProp(7, myObj, 'myUndefined'); // adding an accessor descriptor (only getter) - configurable, enumerable setProp(11, myObj, 'myDate', function() { return new Date(); }); // adding an accessor descriptor (only setter) - not configurable, not enumerable setProp(8, myObj, 'myAlert', null, function(sTxt) { alert(sTxt); }); myObj.myAlert = myObj.myDate.toLocaleString() + '\n\n' + myObj.myString + '\nThe number ' + myObj.myNumber + ' represents the following bitmask: ' + myObj.myArray.join(', ') + '.'; // listing the enumerable properties var sList = 'Here are the enumerable properties of myObj object:\n'; for (var sProp in myObj) { sList += '\nmyObj.' + sProp + ' => ' + myObj[sProp] + ';' } alert(sList);
新しい非ネイティブ Object.setProperty()
メソッドを生成する
匿名のコンストラクタと Object
の setProperty()
という名前のカスタムメソッドを通して取得した記述子オブジェクトにより同じことができます:
// creating a new Object method named Object.setProperty() new (function() { var oDesc = this; Object.setProperty = function(nMask, oObj, sKey, vVal_fGet, fSet) { if (nMask & 8) { // accessor descriptor if (vVal_fGet) { oDesc.get = vVal_fGet; } else { delete oDesc.get; } if (fSet) { oDesc.set = fSet; } else { delete oDesc.set; } delete oDesc.value; delete oDesc.writable; } else { // data descriptor if (arguments.length > 3) { oDesc.value = vVal_fGet; } else { delete oDesc.value; } oDesc.writable = Boolean(nMask & 4); delete oDesc.get; delete oDesc.set; } oDesc.enumerable = Boolean(nMask & 1); oDesc.configurable = Boolean(nMask & 2); Object.defineProperty(oObj, sKey, oDesc); return oObj; }; })(); // creating a new empty object var myObj = {}; // adding a writable data descriptor - not configurable, not enumerable Object.setProperty(4, myObj, 'myNumber', 25); // adding a readonly data descriptor - not configurable, enumerable Object.setProperty(1, myObj, 'myString', 'Hello world!'); // etc. etc.
注記:
Object.setProperty()
メソッドも JavaScript の新しいネイティブメソッドとして提案される可能性があります (ECMAScript bug 335 を参照)。構文
Object.setProperty(bitmask, obj, prop[, value/getter[, setter]])
引数
bitmask
- 記述子ビットマスク (下記参照)。
obj
- プロパティが定義されるオブジェクト。
prop
- 定義または修正されるプロパティの名前。
value/getter
- 任意。データ記述子に割り当てる値、または、(ビットマスクに依存した) アクセサ記述子に割り当てる getter 関数 (bitmask に依存)。
setter
- 任意。アクセサ記述子に割り当てる setter 関数。フラグ
0x8
が データ記述子 に設定されている場合、この引数は無視されます。
説明
非ネイティブの Object.setProperty()
メソッドは、記述子ビットマスクで置き換えられた記述子オブジェクトに対するもの除き、ネイティブの Object.defineProperty()
メソッドのように動作します。bitmask
引数は次の構造を持ちます:
- flag
0x1
- プロパティは列挙可です。
- flag
0x2
- プロパティは設定可です。
- flag
0x4
- プロパティは書込可です。
- flag
0x8
- プロパティはアクセサ記述子です。
そのため、記述子ビットマスクは下記の可能な数値を持ちます:
0
: 読取専用の データ 記述子を表します。設定不可、列挙不可 (0000
)1
: 読取専用の データ 記述子を表します。設定不可、列挙可 (0001
)2
: 読取専用の データ 記述子を表します。設定可、列挙不可 (0010
)3
: 読取専用の データ 記述子を表します。設定可、列挙可 (0011
)4
: 書込可能な データ 記述子を表します。設定不可、列挙不可 (0100
)5
: 書込可能な データ 記述子を表します。設定不可、列挙可 (0101
).6
: 書込可能な データ 記述子を表します。設定可、列挙不可 (0110
).7
: 書込可能な データ 記述子を表します。設定可、列挙可 (0111
).8
: アクセサ 記述子を表します。設定不可、列挙不可 (1000
).9
: アクセサ 記述子を表します。設定不可、列挙可 (1001
).10
: アクセサ 記述子を表します。設定可、列挙不可 (1010
).11
: アクセサ 記述子を表します。設定可、列挙可 (1011
).
注記: フラグ
0x8
が アクセサ記述子 に設定されている場合、フラグ 0x4
(書込可能) は無視されます。設定されていない場合、setter
引数は無視されます。HTMLSelectElement.selectedIndex 実装
ネイティブオブジェクトとともに Object.defineProperty()
メソッドを使用することもできます。次の例では、ラジオボタングループで HTMLSelectElement
の selectedIndex
を実装する方法を示します。
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Radio group selectedIndex example</title> <script type="text/javascript"> Object.defineProperty(NodeList.prototype, 'selectedIndex', { get: function() { var nIndex = this.length - 1; while (nIndex > -1 && !this[nIndex].checked) { nIndex--; } return nIndex; }, set: function(nNewIndex) { if (isNaN(nNewIndex)) { return; } var nOldIndex = this.selectedIndex; if (nOldIndex > -1) { this[nOldIndex].checked = false; } if (nNewIndex > -1) { this[nNewIndex].checked = true; } }, enumerable: true, configurable: false }); // try it! function checkForm() { var nSelectedIndex = document.myForm.myRadioGroup.selectedIndex; if (nSelectedIndex < 0) { alert('Select a gadget!!'); return false; } alert('Congratulations!! You selected the ' + document.myForm.myRadioGroup[nSelectedIndex].value + '.'); return true; } </script> </head> <body> <form name="myForm" onsubmit="return(checkForm());"> <fieldset><legend>Select a gadget</legend> <p><input type="radio" name="myRadioGroup" id="ourShirt" value="shirt" /> <label for="ourShirt">shirt</label><br /> <input type="radio" name="myRadioGroup" id="ourPants" value="pants" /> <label for="ourPants">pants</label><br /> <input type="radio" name="myRadioGroup" id="ourBelt" value="belt" /> <label for="ourBelt">belt</label><br /> <input type="radio" name="myRadioGroup" id="ourShoes" value="shoes" /> <label for="ourShoes">shoes</label></p> <p><span style="cursor:pointer;text-decoration:underline;color:#0000ff;" onclick="document.myForm.myRadioGroup.selectedIndex=2;">Select our favorite gadget ;-)</span></p> <p><input type="submit" value="Order!" /> </fieldset> </form> </body> </html>