【问题标题】:JavaScript property & field reflectionJavaScript 属性和字段反射
【发布时间】:2013-05-12 21:48:13
【问题描述】:

我在 JavaScript 中遇到了这个用于属性反射的小 sn-p 代码:

function GetProperties(obj) {
    var result = [];
    for (var prop in obj) {
        if (typeof obj[prop] !== "function") {
            result.push(prop);
        }
    }
    return result;
}

我已经使用以下“CustomObject”对其进行了测试:

var CustomObject = (function () {
    function CustomObject() {
        this.message = "Hello World";
        this.id = 1234;
    }

    Object.defineProperty(CustomObject.prototype, "Foo", {
        get: function () {
            return "foo";
        },
        enumerable: true,
        configurable: true
    });

    Object.defineProperty(CustomObject.prototype, "Bar", {
        get: function () {
            return "bar";
        },
        enumerable: true,
        configurable: true
    });

    return CustomObject;
})();

这是一个使用 jQuery 的小测试:

$(document).ready(function () {
    console.log(GetProperties(new CustomObject()));
});

结果如下:

["message", "id", "Foo", "Bar"]

我知道 GetProperties 函数只返回输入对象中不是函数的任何内容的数组,但我想过滤结果以仅获取“真实”属性,所以我的输出应该是:

["Foo", "Bar"]

这可能吗?

另外,我可以做相反的事情,只返回字段吗?

【问题讨论】:

    标签: javascript object reflection properties field


    【解决方案1】:

    错误的代码。我要离开(带评论)它会引起后续讨论 可能会帮助其他人。

    如果您总是使用 defineProperty() 来获取不可枚举的属性,那么这将起作用:

    function GetProperties(obj) {
        var result = [];
        for (var prop in obj) {
            // propertyIsEnumerable() returns false just because the properties
            // are inherited thru the prototype chain. It was just a coincidence
            // that it got the desired result. Don't do this.
            if (typeof obj[prop] !== "function" && !obj.propertyIsEnumerable(prop)) {
                result.push(prop);
            }
        }
        return result;
    }
    

    否则,我很想知道问题的一般解决方案。

    编辑:我看到代码有enumerable: true,但我的代码仍然完全按照要求执行。加倍你发球吗?

    【讨论】:

    • 没有理由在循环中使用!obj.propertyIsEnumerable(prop)。如果该属性不可枚举,则无论如何都会跳过该属性。
    • 双WTF,然后呢?等等,我正在 shell 中运行代码。去本地试试看能不能得到同样的结果。编辑:在本地尝试,结果相同。
    • 是的,这很奇怪。 obj.propertyIsEnumerable(prop) 正在为未通过 defineProperty 添加的属性返回 false... 并且它们显然正在被枚举。 FF 和 Chrome 中的行为相同。对于名为 propertyIsEnumerable 的方法来说,这是一种奇怪的行为
    • 啊,我明白了。我倒过来了。它说原型链上的那些是不可枚举的。检查规范,propertyIsEnumerable 没有查看原型属性。 15.2.4.7 Object.prototype.propertyIsEnumerable "注意 1 此方法不考虑原型链中的对象。"
    • 对 JavaScript 的信任恢复了,然后... :D
    【解决方案2】:

    您可以做两件事(可能更多,这取决于您的具体情况):

    1. 以不同的方式命名“私有”属性,例如使用尾随下划线,并在您迭代属性(并排除它们)时检查属性名称是否以下划线结尾。

    2. 1234563或者,您可以使用 Object.getPrototypeOf 并仅迭代原型的属性。

    【讨论】:

    • 在问了另一个问题 (stackoverflow.com/questions/16688537/…) 之后,我明白了在对象或原型上实现属性之间的区别。在此之前我的理解是,在原型上实现的任何东西都会成为构造原型的任何东西的实例成员。我现在可以看到区别了。
    猜你喜欢
    • 2012-01-30
    • 2012-08-08
    • 1970-01-01
    • 2012-05-06
    • 2013-04-24
    • 2010-10-22
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多