Search code examples
javascriptpropertiesprototype

Object vs. function prototype properties - which should predominate?


I have the following code:

Object.defineProperty(Object.prototype, 'json', {
    configurable: true, enumerable: false, writable: true,
    value: function() { return 'Object.json' }
});
function Body() {
    return 1
}
Object.defineProperty(Body.prototype, 'json', {
    configurable: true, enumerable: false, writable: true,
    value: function() { return 'Body.json' }
});
console.log(Body.json())

which, when I run I get an unexpected result:

Object.json

I gather that a function is an object, in the loosest sense of the word (because typeof will return different values) and that therefore, functions may inherit from objects, but if a function is derived from object, I would expect its properties to override or hide those of the base class. yet, the result shows otherwise

how can this be and how can I get the property defined on the function to override that defined on object?


Solution

  • When you call Body.json(), you're not calling json() on an "instance" of Body, but on Body itself, which inherits from the Object prototype.

    If you define the property on Body itself, it will take precedence when evaluating your Body.json() call:

    Object.defineProperty(Object.prototype, 'json', {
        configurable: true, enumerable: false, writable: true,
        value: function() { return 'Object.json' }
    });
    
    function Body() {
        return 1
    }
    
    Object.defineProperty(Body, 'json', {
        configurable: true, enumerable: false, writable: true,
        value: function() { return 'Body.json' }
    });
    
    console.log(Body.json()); // "Body.json"

    Alternatively, if you define the property on the Body prototype and invoke the method on an instance of Body, you will also get the expected result:

    Object.defineProperty(Object.prototype, 'json', {
        configurable: true, enumerable: false, writable: true,
        value: function() { return 'Object.json' }
    });
    
    function Body() {
        return 1
    }
    
    Object.defineProperty(Body.prototype, 'json', {
        configurable: true, enumerable: false, writable: true,
        value: function() { return 'Body.json' }
    });
    
    console.log(new Body().json()); // "Body.json"