Search code examples
javascriptjsonnode.jswebstorm

Method Added to JavaScript Object Class Appears when Traversing through Given Object


In my journey to become stronger in JavaScript, I have taken up a challenge to add a method, myMethod(), to the JavaScript Object class that can be called on a given Object, myObject, in order to manipulate its contents.

I have gotten as far as adding myMethod() to the Object prototype and traversing through myObject via myObject.myMethod(); however, I'm running into a curious problem: at the end of the given object, myMethod() is printed as an value of myObject even though, to my knowledge, it should not be.

Object.prototype.myMethod = function()
{
    for (var key in this)
    {
        console.log(this[key]);
    }
}


function processData(input)
{
    //Enter your code here
    var myObject = JSON.parse("{ \"myParam\": \"myValue\", \"anotherParam\": 123 }");
    myObject.myMethod();
}

The following is the output of this code:

myValue
123
[Function]

Changing myObject[key] to myObject[key].toString() has the following output:

myValue
123
function ()
{
    for (var key in this)
    {
        console.log(this[key].toString());
    }
}

I am executing this script in WebStorm using a Node.js runtime.

The requirements of this challenge only calls for the contents of myObject, and I can't figure out how to stop myMethod() from showing up here. Is there something I'm missing?


Solution

  • In my journey to become stronger in JavaScript, I have taken up a challenge to add a method, myMethod(), to the JavaScript Object class that can be called on a given Object, myObject, in order to manipulate its contents.

    Beware that this practice is seriously frowned-upon (here in 2017, possibly more than it strictly necessary*). Extending any built-in prototype is a bit fraught, but extending Object.prototype is particularly problematic since, of course, almost all objects inherit from it.

    But if you're going to extend a prototype, it's important to add a non-enumerable property via Object.defineProperty or similar:

    Object.defineProperty(Object.prototype, "myMethod", {
        value: function() { /* ... */ }
    });
    

    The default for enumerable is false, so it won't show up in for-in loops, Object.keys arrays, etc.


    * The "don't extend built-in prototypes" mantra started before ES5's introduction of a way of defining non-enumerable properties (e.g., defineProperty). Now that we can define non-enumerable properties, the chief concern is inter-script conflict, each trying to use the same name for something, or conflict with new features as they're added to JavaScript.