めもです。
がいよう
オブジェクトの各プロパティには以下の属性がある。
- データプロパティのみ
[[Value]]
[[Writable]]
- アクセサープロパティのみ
[[Get]]
[[Set]]
- 全プロパティ共通
[[Enumerable]]
[[Configurable]]
プロパティ属性の取得
Object.getOwnPropertyDescriptor(object, propertyName)
を使う。戻り値の value
は [[Value]]
に、writable
は [[Writable]]
に、以下同様、対応している。
Object.getOwnPropertyDescriptor(window, 'NaN');
// => {value: NaN, writable: false, enumerable: false, configurable: false}
プロパティ属性の設定
主にObject.defineProperty(object, propertyName, descriptor)
を使う。省略した属性の値は false
や undefined
になる。
Object.defineProperty(document, 'myProperty', {
writable: true,
enumerable: true,
});
Object.getOwnPropertyDescriptor(document, 'myProperty');
// => {value: undefined, writable: true, enumerable: true, configurable: false}
データプロパティの [[Value]] と [[Writable]]
データプロパティは [[Value]]
と [[Writable]]
のどちらかがある (undefinedでない) プロパティのこと。 obj.face = 'ヮ'
など普通に代入するとこれになる。
[[Value]]
プロパティの値。
var obj = {};
obj.face = 'ω';
Object.getOwnPropertyDescriptor(obj, 'face');
// => {value: "ω", writable: true, enumerable: true, configurable: true}
[[Writable]]
プロパティの値を変更できるかどうか。
[[Writable]]
でないプロパティに代入すると、strict モードなら TypeError
例外が投げられ、そうでなければ無視される。
var obj = {};
Object.defineProperty(obj, 'face', {
value: 'ᴗ',
writable: false,
});
obj.face = 'へ';
console.log(obj.face); // => ᴗ
(function() {
"use strict";
obj.face = 'へ'; // => TypeError!
})();
アクセサープロパティの [[Get]] と [[Set]]
アクセサープロパティは [[Get]]
と [[Set]]
のどちらかがある (undefinedでない) プロパティのこと。
[[Get]]
引数を受け取らない関数。プロパティの値を取得する時に呼ばれる。
var obj = {};
Object.defineProperty(obj, 'name', {
get: function() { return '坂上陽三'; }
});
console.log(obj.name); // => 坂上陽三
[[Set]]
引数を1個受け取る関数。プロパティに値を割り当てる時に呼ばれる。
var obj = {};
Object.defineProperty(obj, 'name', {
get: function() { return '坂上陽三'; }
});
console.log(obj.name); // => 坂上陽三
[[Enumerable]]
for in や Object.keys
で列挙されるかどうか。
var obj = {};
Object.defineProperty(obj, 'visible', {
enumerable: true,
});
Object.defineProperty(obj, 'hidden', {
enumerable: false,
});
Object.keys(obj); // => ["visible"]
[[Configurable]]
[[Configure]] === false だと
- プロパティを削除できない
- [[Value]] 以外の属性を変更できない
var obj = {};
Object.defineProperty(obj, 'x', {
configurable: false,
});
delete obj.x; // => false
Object.defineProperty(obj, 'x', {writable: true}); // => TypeError!
Object.defineProperty(obj, 'x', {enumerable: true}); // => TypeError!
Object.defineProperty(obj, 'x', {configurable: true}); // => TypeError!
Object.defineProperty(obj, 'x', {get: Date.now}); // => TypeError!
Object.defineProperty(obj, 'x', {set: alert.bind(window)}); // => TypeError!
Object.defineProperty(obj, 'x', {value: 'y'}); // => ok
Object.x = 'X'; // => ok
ついでにオブジェクトの [[Extensible]]
オブジェクトの [[Extensible]]
属性が false
だとプロパティを追加できない。
Object.preventExtensions
と Object.isExtensible
を使ってアクセスする。
var obj = {};
Object.isExtensible(obj); // => true
obj.x = 'x';
Object.preventExtensions(obj);
Object.isExtensible(obj); // => false
obj.y = 'y';
obj.y; // => undefined
(function() {
"use strict";
obj.y = 'y'; // => TypeError!
})();
属性をまとめて false にするメソッド
Object.seal
Object.freeze
Object.seal(あざらし)
は あざらし
の[[Extensible]]
を false
にし、各プロパティの [[Configurable]]
を false
にする。
Object.freeze(あざらし)
は Object.seal
の処理に加えて、あざらし
の各プロパティの[[Writable]]
を false
にする。
たとえば配列を seal すると固定長になり、freeze すると不変になる。