0

I came across this little snippet of code for property reflection in JavaScript:

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

I've tested it using the following "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;
})();

Here is a little test using jQuery:

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

Here are the results:

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

I understand that the GetProperties function just returns an array of anything in the input object that is not a function, but I want to filter the results to get only the "real" properties, so my output should be:

["Foo", "Bar"]

Is this possible?

Also, can I do the opposite and just return the fields?

2 Answers 2

1

There are two things you could do (and possibly more, it depends on your exact situation):

  1. Name "private" properties differently, e.g. with a trailing underscore and check whether the property name ends with an underscore when you are iterating over the properties (and exclude them).

  2. If by "real properties" you mean the properties defined on the prototype and you want to ignore all properties defined on the object itself, you can use .hasOwnPrototype to check where it is defined. Alternatively, you could use Object.getPrototypeOf and iterate over the properties of the prototype only.

Sign up to request clarification or add additional context in comments.

1 Comment

After asking another question (stackoverflow.com/questions/16688537/…), I understood the difference between implementing properties on the object or on the prototype. My understanding prior to this was that anything implemented on the prototype became an instance member for anything that constructed the prototype. I can now see the difference.
0

Bad code. I'm leaving (with a comment) it 'cause the subsequent discussion might help somebody else.

If you always use defineProperty() to get non enumerable properties, then this would work:

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;
}

Otherwise, I'd be curious to know a general solution to the problem.

EDIT: I see that the code has enumerable: true and still my code does exactly what was asked. Double you tee ef?

6 Comments

There's no reason for a !obj.propertyIsEnumerable(prop) in a loop. If the property is not enumerable, that that property will be skipped anyway.
Double WTF, then? Wait, I'm, running the code in a shell. Gonna try it locally and see if I get the same result. EDIT: Tried locally, same result.
Yeah, this is weird. obj.propertyIsEnumerable(prop) is returning false for the properties that were not added via defineProperty... and they're clearly being enumerated. Same behavior in FF and Chrome. That's a strange behavior for a method called propertyIsEnumerable
Ah, I see what it is. I had it backwards. It says the ones on the prototype chain are not enumerable. Checked with the spec, and the propertyIsEnumerable doesn't look at prototyped properties. 15.2.4.7 Object.prototype.propertyIsEnumerable "NOTE 1 This method does not consider objects in the prototype chain."
Faith in JavaScript restored, then... :D
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.