LoginSignup
2
3

More than 3 years have passed since last update.

javascript の Object のメソッドにおける列挙可能とか直接所有とかの扱い

Posted at

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をそれぞれ指定できるやつがあればいいんだけど。
コードが冗長なのは気にしない。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3