我在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时都会调用它。
答案 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);
答案 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。