如何确保从JavaScript中的原型继承的每个对象的唯一ID?

时间:2016-06-06 14:46:01

标签: javascript inheritance prototype

我在JavaScript中有这样的构造函数:

var BaseThing = function() {
  this.id = generateGuid();
}

正如您所期望的,当您创建新的BaseThing时,ID每次都是唯一的。

var thingOne = new BaseThing();
var thingTwo = new BaseThing();
console.log(thingOne.id === thingTwo.id); // false

但是当我尝试创建从BaseThing继承的对象时,事情变得很糟糕:

var FancyThing = function() {
   this.fanciness = "considerable";
}
FancyThing.prototype = new BaseThing();

var thingOne = new FancyThing();
var thingTwo = new FancyThing();
console.log(thingOne.id === thingTwo.id); // true

这当然是有道理的,因为原型继承的工作方式,但它不是我想要的;我希望ID是唯一的,而不必在从BaseThing继承的每个对象上重新实现它。

最好的方法是什么?我能想出的唯一解决方案是(a)重新实现每个子构造函数的id(但这似乎打败了继承点)或(b)为BaseThing添加了某种初始化函数(但我没有我不得不担心每次创建Thing时都会调用它。

3 个答案:

答案 0 :(得分:3)

问题是您的孩子没有从父母继承构造函数(函数体)。您可以先应用父函数,这样可以提供所需的效果,而无需重新写入父级中包含的所有内容。这可以使用.apply

来完成

var counter = 0;
function generateGuid() { return ++counter; }

var BaseThing = function() {
  this.id = generateGuid();
}

var thingOne = new BaseThing();
var thingTwo = new BaseThing();
console.log(thingOne.id === thingTwo.id); // false


var FancyThing = function() {
  BaseThing.apply(this, arguments) // inherit
  this.fanciness = "considerable";
}
FancyThing.prototype = Object.create(BaseThing.prototype, {constructor: {value: FancyThing, writable: true, configurable: true}});

var thingOne = new FancyThing();
var thingTwo = new FancyThing();
console.log(thingOne.id === thingTwo.id); // false

不幸的是,我不知道从父级扩展的方法,而不必以某种方式定义父级被调用。

答案 1 :(得分:2)

是的,相当于打电话给超级本不是一个糟糕的方式。除了申请之外,您还可以使用电话:

function generateGuid(){
    return Math.random(); 
}

var BaseThing = function() {
  this.id = generateGuid();
}

var FancyThing = function() {
   BaseThing.call(this);
   this.fanciness = "considerable";
}


var o = new FancyThing();
console.log(o);

https://repl.it/CYp1/0

答案 2 :(得分:2)

你可以通过将id属性移动到BaseThing.prototype并使其成为"计算"使用Object.defineProperty

var BaseThing = function() {
  //will define id on prototype
  //this.id = generateGuid();
}

Object.defineProperty(BaseThing.prototype, 'id', {
  configurable: true,
  enumerable: true,
  get: function() {
    //redefine property on first call
    Object.defineProperty(this, 'id', {
        configurable: false,
        enumerable: true,
        value: generateGuid()
    })

    return this.id
  }
})

Demo