通过在"命名空间中添加函数来扩展对象原型"

时间:2015-10-13 11:21:15

标签: javascript prototype

以下代码(也在Plunker中)改编自this SO post。 我正在尝试实现相同的逻辑,只在uniqueId的特殊属性中添加Object.prototype函数以保持清晰。

以下代码在使用nodejs运行时也有效(HTML-ized Plunker示例也可以)。即控制台打印三个唯一对象标识符:012

但是,当test切换变量设置为1时,控制台会打印000

如何在uniqueId命名空间中添加foo函数?

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()+']');
}

1 个答案:

答案 0 :(得分:2)

您需要使用getter定义foo,以允许它访问this以便在子方法的散列中使用:

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;
        }
      };
    }
  });

}

现在

defineFoo();
obj.foo.uniqueId()

如果您愿意,可以选择使用self

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