プロパティの列挙可能性と所有権

この記事は技術レビューを必要としています。ぜひご協力ください

この記事は編集レビューを必要としています。ぜひご協力ください

この翻訳は不完全です。英語から この記事を翻訳 してください。

列挙可能な (enumerable)プロパティとは、内部の [[Enumerable]] フラグがtrueに設定されているものであり、単純な代入や初期化で生成されたプロパティはデフォルトでそうなります(一方、Object.defineProperty()で追加したプロパティはデフォルトで [[Enumerable]] が false になります)。 列挙可能なプロパティは、名前がSymbolである場合を除いて、 for...in ループの対象になります。
直接所有の (own)プロパティとは、プロトタイプチェーン上ではなく、オブジェクトに直接属しているプロパティのことです。
プロパティはまとめて取り扱うこともでき、プロパティの検出、取得、反復/列挙 に関連する多数の組み込み機能があります。それらを下図に示します。 その下にあるサンプルコードでは、組み込み機能が対応しないカテゴリに対応する方法を示します。

プロパティの列挙可能性と直接所有 - 検出、取得 および 反復
機能 直接所有するオブジェクト 直接所有するオブジェクトとプロトタイプチェーン プロトタイプチェーンのみ
検出
列挙可能 列挙不可能 列挙可能と列挙不可能
propertyIsEnumerable hasOwnProperty と、 not propertyIsEnumerable hasOwnProperty
追加のコードが必要 追加のコードが必要
取得
列挙可能 列挙不可能 列挙可能と列挙不可能
Object.keys getOwnPropertyNames filtered to include properties when not passing propertyIsEnumerable getOwnPropertyNames
追加のコードが必要 追加のコードが必要
反復
列挙可能 列挙不可能 列挙可能と列挙不可能
Iterate over Object.keys Iterate over getOwnPropertyNames filtered to include properties when not passing propertyIsEnumerable Iterate over getOwnPropertyNames
列挙可能 列挙不可能 列挙可能と列挙不可能
for..in 追加のコードが必要 追加のコードが必要
追加のコードが必要

列挙可能/直接所有の条件でプロパティを取得する方法

以下に示すのは全てのケースで最も効率的なアルゴリズムではなく、簡潔なデモであることに注意してください。

  • 検出は下記で可能です:
    SimplePropertyRetriever.使いたいgetメソッド(obj).indexOf(prop) > -1
  • 反復は下記で可能です:
    SimplePropertyRetriever.使いたいgetメソッド(obj).forEach(function (value, prop) {});  (または filter(), map() 等を使う)
var SimplePropertyRetriever = {
    getOwnEnumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._enumerable); 
         // Or could use for..in filtered with hasOwnProperty or just this: return Object.keys(obj);
    },
    getOwnNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._notEnumerable);
    },
    getOwnEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable); 
        // Or just use: return Object.getOwnPropertyNames(obj);
    },
    getPrototypeEnumerables: function (obj) {
        return this._getPropertyNames(obj, false, true, this._enumerable);
    },
    getPrototypeNonenumerables: function (obj) {
        return this._getPropertyNames(obj, false, true, this._notEnumerable);
    },
    getPrototypeEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
    },
    getOwnAndPrototypeEnumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._enumerable); 
        // Or could use unfiltered for..in
    },
    getOwnAndPrototypeNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._notEnumerable);
    },
    getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
        return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
    },
    // Private static property checker callbacks
    _enumerable : function (obj, prop) {
        return obj.propertyIsEnumerable(prop);
    },
    _notEnumerable : function (obj, prop) {
        return !obj.propertyIsEnumerable(prop);
    },
    _enumerableAndNotEnumerable : function (obj, prop) {
        return true;
    },
    // Inspired by http://stackoverflow.com/a/8024294/271577
    _getPropertyNames : function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
        var props = [];

        do {
            if (iterateSelfBool) {
                Object.getOwnPropertyNames(obj).forEach(function (prop) {
                    if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
                        props.push(prop);
                    }
                });
            }
            if (!iteratePrototypeBool) {
                break;
            }
            iterateSelfBool = true;
        } while (obj = Object.getPrototypeOf(obj));

        return props;
    }
};

検出表

  in for..in hasOwnProperty propertyIsEnumerable in Object.keys in Object.getOwnPropertyNames
列挙可能 true true true true true true
列挙不可能 true false true false false true
継承, 列挙可能 true true false false false false
継承, 列挙不可能 true false false false false false
Symbolキーが含まれるか true false true true false false

関連情報

ドキュメントのタグと貢献者

タグ: 
 このページの貢献者: ambi, taiyaki32p, shide55
 最終更新者: ambi,