Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27286

Extending Object prototype by adding a function in a "namespace"

The below code (also in Plunker) is adapted from this SO post. I am trying to implement the same logic, only add the uniqueId function in a special property of the Object.prototype to keep things clear.

The below code works when run using nodejs (also the HTML-ized Plunker example works as well). I.e. the console prints three unique object identifiers: 0, 1 and 2.

However, when the test switch variable is set to 1, console prints 0, 0 and 0.

What should I do to add the uniqueId function in the foo namespace?

function addUniqueId1(){
    if (Object.prototype.foo===undefined) {
        Object.prototype.foo = {};
        console.log('foo "namespace" added');
    }
    if (Object.prototype.foo.uniqueId===undefined) {
        var i = 0;
        Object.prototype.foo.uniqueId = function() {
            console.log('uniqueId function called');
            if (this.___uniqueId === undefined) {
                this.___uniqueId = i++;
            }
            return this.___uniqueId;
        };
        console.log('function defined');
    }
}


function addUniqueId2() {
    if (Object.prototype.uniqueId === undefined) {
        var i = 0;
        Object.prototype.uniqueId = function() {
            if (this.___uniqueId === undefined) {
                this.___uniqueId = i++;
            }
            return this.___uniqueId;
        };
    };
};


var test=2; // if you set this to 1 it stops working

if (test==1)
    addUniqueId1();
else
    addUniqueId2();

var xs = [{}, {}, {}];
for (var i = 0 ; i < xs.length ; i++) {
    if (test==1)
        console.log('object id is: ['+xs[i].foo.uniqueId()+']');
    else
        console.log('object id is: ['+xs[i].uniqueId()+']');
}

Upvotes: 1

Views: 29

Answers (1)

user663031
user663031

Reputation:

You need to define foo with a getter, to allow it to access this for use within the hash of sub-method(s):

function defineFoo() {
  if (Object.prototype.foo) return;

  var i = 0;

  Object.defineProperty(Object.prototype, 'foo', {
    get: function() {
      var self = this;
      return {
        uniqueId: function() { 
          return self.__uniqueId = self.uniqueId || ++i;
        }
      };
    }
  });

}

Now

defineFoo();
obj.foo.uniqueId()

If you prefer, an alternative to using self:

Object.defineProperty(Object.prototype, 'foo', {
  get: function() {
    return {
      uniqueId: function() { 
         return this.__uniqueId = this.uniqueId || ++i;
      }.bind(this)
    };
  }
});

Upvotes: 2

Related Questions