Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/452.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何确保从JavaScript中的原型继承的每个对象都有唯一的ID?_Javascript_Inheritance_Prototype - Fatal编程技术网

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

如何确保从JavaScript中的原型继承的每个对象都有唯一的ID?,javascript,inheritance,prototype,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 但当我尝试创建从BaseT

我在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添加某种初始化函数(但我不想担心确保每次创建一个对象时都调用它).

问题在于您的孩子没有从父代继承构造函数(函数体)。您可以首先应用parent函数,这将提供所需的效果,而无需重新写入父函数中包含的所有内容。这可以通过使用
.apply
完成

var计数器=0;
函数generateGuid(){return++counter;}
var BaseThing=函数(){
this.id=generateGuid();
}
var thingOne=new BaseThing();
var thingTwo=新的BaseThing();
console.log(thingOne.id==thingTwo.id);//错误的
var FancyThing=函数(){
BaseThing.apply(这个,参数)//inherit
这是“相当大的”;
}
FancyThing.prototype=Object.create(BaseThing.prototype,{constructor:{value:FancyThing,writable:true,configurable:true}});
var thingOne=newfancything();
var thingTwo=新的FancyThing();

console.log(thingOne.id==thingTwo.id);//false
问题在于您的子代没有从父代继承构造函数(函数体)。您可以首先应用parent函数,这将提供所需的效果,而无需重新写入父函数中包含的所有内容。这可以通过使用
.apply
完成

var计数器=0;
函数generateGuid(){return++counter;}
var BaseThing=函数(){
this.id=generateGuid();
}
var thingOne=new BaseThing();
var thingTwo=新的BaseThing();
console.log(thingOne.id==thingTwo.id);//错误的
var FancyThing=函数(){
BaseThing.apply(这个,参数)//inherit
这是“相当大的”;
}
FancyThing.prototype=Object.create(BaseThing.prototype,{constructor:{value:FancyThing,writable:true,configurable:true}});
var thingOne=newfancything();
var thingTwo=新的FancyThing();

console.log(thingOne.id==thingTwo.id);//false
是的,做与调用super相当的事情并不是一个坏方法。除了应用,您还可以使用call:

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

是的,做一个相当于给超级用户打电话的工作并不是一个坏方法。除了应用,您还可以使用call:

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

您可以通过将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
  }
})

您可以通过将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
  }
})

这实际上归结为“如何确保子级调用父级构造函数”。答案是,除了让每个子级在其自己的构造函数中实际调用父级之外,您无法确保这一点。这至少让子类承担了这样的责任,而不是子类的使用者。如何
generateGuid()
工作?它是否知道要为其创建id的对象的类型?也许你可以根据对象的类型传递一个参数并生成特定的id…我想我基本上希望有一个比“每次这样做时都要记住调用父构造函数”更优雅的答案。做“正确的”继承:这实际上归结为“如何确保子代调用父构造函数”。答案是,除了让每个子级在其自己的构造函数中实际调用父级之外,您无法确保这一点。这至少让子类承担了这样的责任,而不是子类的使用者。如何
generateGuid()
工作?它是否知道要为其创建id的对象的类型?也许你可以根据对象的类型传递一个参数并生成特定的id…我想我基本上希望有一个比“记住每次调用父构造函数”更优雅的答案。执行“正确”继承:
apply
可能比
call
更可取,as apply允许您传递一组参数
apply
可能比
call
更可取,as apply允许您传递一组参数
FancyThing.prototype=new BaseThing()应该真正变成
FancyThing.prototype=Object.create(BaseThing.prototype,{constructor:{value:FancyThing,writable:true,configurable:true}})
FancyThing.prototype=newbasething()应该真正变成
FancyThing.prototype=Object.create(BaseThing.prototype,{constructor:{value:FancyThing,writable:true,configurable:true}})。就结果而言,这是最接近要求的结果,但要实现该功能似乎还有很长的路要走。啊哈,这似乎很有效,谢谢!很明显,我需要了解更多关于属性的信息。从结果来看,这是最接近于所要求的,但这项功能似乎还有很长的路要走。啊哈,这似乎很有效,谢谢!显然,我需要更多地了解房地产。