Search code examples
javascriptobjectprototypedefineproperty

How can I add a property to Object.prototype without it being applied to Number.prototype?


My goal is to create a master_script.js. A handler file mainly used in development.

A subsection of this file is dedicated to customizing the prototypes of the foundation objects:

  1. String
  2. Number
  3. Array
  4. Object
  5. Date
  6. Function
  7. Boolean

So as I'm writing out my code blocks...

/********************************************************/
Object.defineProperty(
    Number.prototype,'len',
    {get:function(){
        str=this.toString()
        return str.length
    }}
)
/********************************************************/
n=123
o={123:'abc',abc:123}
/********************************************************/
console.log(
    'n              ⇒ ',n,
    '\n n.len       ⇒ ',n.len,
    '\n n.__proto__ ⇒ ',n.__proto__
)
/********************************************************/

Works fine!

  • when I expand n.__proto__ in the console it displays the len: (...) property and it's getter function get len: function (){.
  • and when I type n. into the console it is clearly visible on the list of properties|methods.

The problems start when I configure the same setup for the o variable:

/********************************************************/
Object.defineProperty(
    Number.prototype,'len',
    {get:function(){
        str=this.toString()
        return str.length
    }}
)
/******************************/
Object.defineProperty(
    Object.prototype,'len',
    {get:function(){
        cnt=0
        for(i in this)  cnt++;
        return cnt
    }}
)
/********************************************************/
n=123
o={123:'abc',abc:123}
/********************************************************/
console.log(
    'n              ⇒ ',n,
    '\n n.len       ⇒ ',n.len,
    '\n n.__proto__ ⇒ ',n.__proto__
)
/******************************/
console.log(
    'o              ⇒ ',o,
    '\n o.len       ⇒ ',o.len,
    '\n o.__proto__ ⇒ ',o.__proto__
)
/********************************************************/

The first thing I notice is that when I now type n. or o. into the console the popup list of properties|methods no longer contains a reference to the len property, but if I type in the full extension n.len or o.len I get the desired result of 3 or 2...

So I know the code is legit but I need the console popup as there is about 40 different properties & methods for each of the 7 foundation objects...

So I wrote a test block to try & identify the problem:

/********************************************************/
Object.defineProperty(
    Object.prototype,'dis',
    {get:function(){return this}}
)
/******************************/
Object.defineProperty(
    Number.prototype,'len',
    {get:function(){return this.length}}
)
/********************************************************/
o={123:'abc',abc:123}
n=123
e=document.createElement('option')
/********************************************************/
console.log(
    'o              ⇒ ',o,
    '\n o.__proto__ ⇒ ',o.__proto__
)
/******************************/
console.log(
    'n              ⇒ ',n,
    '\n n.__proto__ ⇒ ',n.__proto__
)
/******************************/
console.log(
    'e              ⇒ ',e,
    '\n e.__proto__ ⇒ ',e.__proto__
)
/********************************************************/

Immediately after expanding the .__proto__ in the console for o, n and now e, I noticed that all 3 had been given the dis property I had originally tried to assign to solely the o object.

Then I cracked it: Number.prototype itself is an object, ergo it inherits the dis property from the Object.prototype

How can I append the dis property solely to the o object without it being inherited by n from Object.prototype?


Solution

  • A subsection of this file is dedicated to customizing the prototypes of the foundation objects

    Oy vey. Not the greatest idea IMHO. Especially modifying the Object prototype. Yeesh.

    So I know the code is legit but I need the console popup as there is about 40 different properties & methods for each of the 7 foundation objects...

    Why? Are you doing your development in a browser console?

    Do you have the nous to show me how to append the dis property solely to the o object without it being inherited by n from Object.prototype?

    Ok...

    Object.defineProperty(
        o, 'dis',
        { get:function(){ return this; } }
    );
    

    How's that?

    Anything you add to the Object prototype is going to show up on pretty much everything (that's why it's a bad idea).

    Since o only inherits from Object, there's no way to define a property that would only show up on plain objects and not on everything else. Your choices are to:

    • Define the property directly on o, or
    • Instead of using a plain object for o, create o from your own custom type and put your property on the prototype of that custom type (much better than modifying the built-in types' prototypes).


    Note: Of course, you could modify Number.prototype to have a dis property of undefined:

    Object.defineProperty(Number.prototype, 'dis', {
        value: void 0
    });
    
    console.log((9).dis);
    

    That would solve your problem as far as numbers go, but that dis property is still going to be on pretty much everything else in existence.

    And please, for goodness' sake, use semicolons. Think of the children.