corazza
corazza

Reputation: 32354

Iterating through object's properties lists things in the prototype

I'm trying to make a "copy" function and add it to the object's prototype. I planned to recursively typecheck and assign properties to a new object and then return the object... But, there seems to be a problem, see this snippet of code:

Object.prototype.copy = function()
{
    for (prop in this)
    {
        console.log(prop); //Logs copy (the function)!!!
    }
}

x = {"a": 1};
y = x.copy();

As I've pointed out in the comment, I found this very weird behavior, but why is this happening? The copy function should be in Object.prototype, not in the instanced object itself! How do I fix it? Can I just set this.copy = undefined, and still rely on Object.prototype.copy?

This is the full code sample, as requested:

Object.prototype.copy = function()
{
    var object = this; //The object we are copying.
    var newObject = {}; //The object we will return.

    //Cycle through the properties of the object we are creating, copy them recursively.
    for (prop in object)
    {
        if (!Object.prototype.hasOwnProperty.call(this, prop) || object[prop] == null)
        {
            continue;
        }

        if (prop == "copy")
        {
            console.log("Well, blah."); //This never prints!
        }

        if (typeof(object[prop]) == "object" && !(object[prop] instanceof Array)) //If the object's property is another object...
        {
            newObject[prop] = object[prop].copy(); //Set the copy of it to the new object as well.
            console.log("1 --- " + prop); //This prints copy - two times! That defies logic!
        }
        else if (typeof(object[prop]) == "object") //If it's an array...
        {
            newObject[prop] = object[prop].slice(); //Do it in a nicer fashion.
            console.log("2 --- " + prop);
        }
        else //You're safe to copy it.
        {
            newObject[prop] = object[prop];
            console.log("3 --- " + prop + " --- " + object[prop]);
        }
    }

    return newObject;
}

Upvotes: 1

Views: 121

Answers (1)

Pointy
Pointy

Reputation: 413720

There's a method called "hasOwnProperty" that you can use:

 if (this.hasOwnProperty(prop)) { ... }

If the function returns true the it's a "direct" property on the object.

If you fear that the "hasOwnProperty" method may be borked, you can do this:

if (Object.prototype.hasOwnProperty.call(this, prop)) { ... }

instead.

Newer versions of JavaScript have fancier ways of examining and controlling objects.

edit — also your updated code involves a problem that'll bite due to the nested calls to "copy": you didn't declare "prop" with var, so after the call to copy an object, the value of "prop" will have changed! (Every call to "copy" shares the same variable, in other words.)

Upvotes: 3

Related Questions