javascriptのObjectのプロパティにはいろんな種類がある。
[[Enumerable]]
(列挙可能性)みたいな属性がついていたり、「直接所有(own)」か「継承したもの」かの違いだったり、キーがString
だったりSymbol
だったりとかする。
キーや値を取得したり色々するメソッドはいくつかありそれらについての扱いが異なる。
hasOwnProperty
とかassign
とかentries
とかそんなのでどのように扱われているかしらべた。
目的は継承もふくめて取得すること。
#実行したコード
var syms={
// Symbol の一覧
' Own Enumerable Symbol':Symbol(' Own Enumerable Symbol'),
' Own nonEnumerable Symbol':Symbol(' Own nonEnumerable Symbol'),
'nonOwn Enumerable Symbol':Symbol('nonOwn Enumerable Symbol'),
'nonOwn nonEnumerable Symbol':Symbol('nonOwn nonEnumerable Symbol'),
};
// own:直接所有 enumerable:列挙可能性
function C(){
// 直接所有のプロパティを設定
Object.defineProperty(this , ' Own Enumerable String' ,{value: 11,enumerable: true});
Object.defineProperty(this , ' Own nonEnumerable String' ,{value: 22,enumerable:false});
Object.defineProperty(this ,syms[' Own Enumerable Symbol'],{value: 44,enumerable: true});
Object.defineProperty(this ,syms[' Own nonEnumerable Symbol'],{value: 55,enumerable:false});
return this;
}
// プロトタイプを設定
Object.defineProperty(C.prototype, 'nonOwn Enumerable String' ,{value:123,enumerable: true});
Object.defineProperty(C.prototype, 'nonOwn nonEnumerable String' ,{value:345,enumerable:false});
Object.defineProperty(C.prototype,syms['nonOwn Enumerable Symbol'],{value:678,enumerable: true});
Object.defineProperty(C.prototype,syms['nonOwn nonEnumerable Symbol'],{value:890,enumerable:false});
// オブジェクト生成 上で定義した 直接所有/継承 列挙可能/不可能 String/Symbol それぞれのプロパティを持つ
var obj=new C();
// 以下調べるための実行
console.log('entries :',Object.entries (obj));
console.log('getOwnPropertyNames :',Object.getOwnPropertyNames (obj));
console.log('getOwnPropertySymbols:',Object.getOwnPropertySymbols(obj));
console.log('keys :',Object.keys (obj));
console.log('values :',Object.values (obj));
var keys=[];
for(let key in obj)keys.push(key);
console.log('for ... in :',keys);
console.log('getOwnPropertyDescriptors:',Object.getOwnPropertyDescriptors(obj));
console.log('assign:',Object.assign(Object.create(null),obj));
console.log('hasOwnProperty : Own Enumerable String',obj.hasOwnProperty ( ' Own Enumerable String' ));
console.log('hasOwnProperty : Own nonEnumerable String',obj.hasOwnProperty ( ' Own nonEnumerable String' ));
console.log('hasOwnProperty : nonOwn Enumerable String',obj.hasOwnProperty ( 'nonOwn Enumerable String' ));
console.log('hasOwnProperty : nonOwn nonEnumerable String',obj.hasOwnProperty ( 'nonOwn nonEnumerable String' ));
console.log('hasOwnProperty : Own Enumerable Symbol',obj.hasOwnProperty (syms[' Own Enumerable Symbol']));
console.log('hasOwnProperty : Own nonEnumerable Symbol',obj.hasOwnProperty (syms[' Own nonEnumerable Symbol']));
console.log('hasOwnProperty : nonOwn Enumerable Symbol',obj.hasOwnProperty (syms['nonOwn Enumerable Symbol']));
console.log('hasOwnProperty : nonOwn nonEnumerable Symbol',obj.hasOwnProperty (syms['nonOwn nonEnumerable Symbol']));
console.log('propertyIsEnumerable : Own Enumerable String',obj.propertyIsEnumerable( ' Own Enumerable String' ));
console.log('propertyIsEnumerable : Own nonEnumerable String',obj.propertyIsEnumerable( ' Own nonEnumerable String' ));
console.log('propertyIsEnumerable : nonOwn Enumerable String',obj.propertyIsEnumerable( 'nonOwn Enumerable String' ));
console.log('propertyIsEnumerable : nonOwn nonEnumerable String',obj.propertyIsEnumerable( 'nonOwn nonEnumerable String' ));
console.log('propertyIsEnumerable : Own Enumerable Symbol',obj.propertyIsEnumerable(syms[' Own Enumerable Symbol']));
console.log('propertyIsEnumerable : Own nonEnumerable Symbol',obj.propertyIsEnumerable(syms[' Own nonEnumerable Symbol']));
console.log('propertyIsEnumerable : nonOwn Enumerable Symbol',obj.propertyIsEnumerable(syms['nonOwn Enumerable Symbol']));
console.log('propertyIsEnumerable : nonOwn nonEnumerable Symbol',obj.propertyIsEnumerable(syms['nonOwn nonEnumerable Symbol']));
#出力
多少見やすいように成型
GoogleChromeとFirefoxで差はなし。
entries : [Array(2)]
0: (2) [" Own Enumerable String", 11]
getOwnPropertyNames : (2) [" Own Enumerable String", " Own nonEnumerable String"]
getOwnPropertySymbols: (2) [Symbol( Own Enumerable Symbol), Symbol( Own nonEnumerable Symbol)]
keys : [" Own Enumerable String"]
values : [11]
for ... in : (2) [" Own Enumerable String", "nonOwn Enumerable String"]
getOwnPropertyDescriptors: {...}
" Own Enumerable String": {value: 11, writable: false, enumerable: true, configurable: false}
" Own nonEnumerable String": {value: 22, writable: false, enumerable: false, configurable: false}
Symbol( Own Enumerable Symbol): {value: 44, writable: false, enumerable: true, configurable: false}
Symbol( Own nonEnumerable Symbol): {value: 55, writable: false, enumerable: false, configurable: false}
assign: {...}
" Own Enumerable String": 11
Symbol( Own Enumerable Symbol): 44
hasOwnProperty : Own Enumerable String true
hasOwnProperty : Own nonEnumerable String true
hasOwnProperty : nonOwn Enumerable String false
hasOwnProperty : nonOwn nonEnumerable String false
hasOwnProperty : Own Enumerable Symbol true
hasOwnProperty : Own nonEnumerable Symbol true
hasOwnProperty : nonOwn Enumerable Symbol false
hasOwnProperty : nonOwn nonEnumerable Symbol false
propertyIsEnumerable : Own Enumerable String true
propertyIsEnumerable : Own nonEnumerable String false
propertyIsEnumerable : nonOwn Enumerable String false
propertyIsEnumerable : nonOwn nonEnumerable String false
propertyIsEnumerable : Own Enumerable Symbol true
propertyIsEnumerable : Own nonEnumerable Symbol false
propertyIsEnumerable : nonOwn Enumerable Symbol false
propertyIsEnumerable : nonOwn nonEnumerable Symbol false
#結果
enumerable | own | String/Symbol | 動作 | 列挙可/不可能性 | 直接所有/継承 | |
---|---|---|---|---|---|---|
entries | true | true | String | 取得 | 可能のみ | 直接所有のみ |
getOwnPropertyNames | true/false | true | String | 取得 | 両方 | 直接所有のみ |
getOwnPropertySymbols | true/false | true | Symbol | 取得 | 両方 | 直接所有のみ |
keys | true | true | String | 取得 | 可能のみ | 直接所有のみ |
values | true | true | String | 取得 | 可能のみ | 直接所有のみ |
for ... in | true | true/false | String | 取得 | 可能のみ | 両方 |
getOwnPropertyDescriptors | true/false | true | String/Symbol | 取得 | 両方 | 直接所有のみ |
assign | true | true | String/Symbol | 代入 | 可能のみ | 直接所有のみ |
hasOwnProperty | true/false | true | String/Symbol | 検査 | 両方 | 直接所有のみ |
propertyIsEnumerable | true | true | String/Symbol | 検査 | 可能のみ | 直接所有のみ |
#結論
直接所有/継承の両方を取得するにはfor ... in
を使うことになりそう。
ただしSymbol
が含まれないのでそれを含めようと思ったら面倒くさいことになりそう。
列挙可/不可能性,直接所有/継承,String/Symbolをそれぞれ指定できるやつがあればいいんだけど。
コードが冗長なのは気にしない。