Enumerability and ownership of properties - JavaScript 编辑

Enumerable properties are those properties whose internal enumerable flag is set to true, which is the default for properties created via simple assignment or via a property initializer (properties defined via Object.defineProperty and such default enumerable to false). Enumerable properties show up in for...in loops unless the property's key is a Symbol. Ownership of properties is determined by whether the property belongs to the object directly and not to its prototype chain. Properties of an object can also be retrieved in total. There are a number of built-in means of detecting, iterating/enumerating, and retrieving object properties, with the chart showing below which are available. Some sample code follows which demonstrates how to obtain the missing categories.

Property enumerability and ownership - built-in methods of detection, retrieval, and iteration
FunctionalityOwn objectOwn object and its prototype chainPrototype chain only
Detection
EnumerableNonenumerableEnumerable and Nonenumerable

propertyIsEnumerable

hasOwnProperty

hasOwnProperty – filtered to exclude enumerables using propertyIsEnumerable

hasOwnProperty
EnumerableNonenumerableEnumerable and Nonenumerable
Not available without extra codeNot available without extra codein
Not available without extra code
Retrieval
EnumerableNonenumerableEnumerable and Nonenumerable

Object.keys

getOwnPropertyNames 

getOwnPropertySymbols

getOwnPropertyNames, getOwnPropertySymbols – filtered to exclude enumerables using propertyIsEnumerable

getOwnPropertyNames

getOwnPropertySymbols

Not available without extra codeNot available without extra code
Iterable
EnumerableNonenumerableEnumerable and Nonenumerable

Object.keys

getOwnPropertyNames 

getOwnPropertySymbols

getOwnPropertyNames, getOwnPropertySymbols – filtered to exclude enumerables using propertyIsEnumerable

getOwnPropertyNames

getOwnPropertySymbols

EnumerableNonenumerableEnumerable and Nonenumerable

for..in

(excluding symbols)

Not available without extra codeNot available without extra code
Not available without extra code

Obtaining properties by enumerability/ownership

Note that this is not the most efficient algorithm for all cases, but useful for a quick demonstration.

  • Detection can occur by SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) > -1
  • Iteration can occur by SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {}); (or usefilter(), map(), etc.)
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;
    }
};

Detection Table

infor..inobj.hasOwnPropertyobj.propertyIsEnumerableObject.keysObject.getOwnPropertyNamesObject.getOwnPropertyDescriptorsReflect.ownKeys()
Enumerabletruetruetruetruetruetruetruetrue
Nonenumerabletruefalsetruefalsefalsetruetruetrue
Symbols keystruefalsetruetruefalsefalsetruetrue
Inherited Enumerabletruetruefalsefalsefalsefalsefalsefalse
Inherited Nonenumerabletruefalsefalsefalsefalsefalsefalsefalse
Inherited Symbols keystruefalsefalsefalsefalsefalsefalsefalse

See also

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

词条统计

浏览:139 次

字数:12840

最后编辑:7 年前

编辑次数:0 次

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文