在javascript中扩展继承的原型对象

时间:2014-07-03 11:44:44

标签: javascript prototype extend

Plunker - http://plnkr.co/edit/9tRSsBw2upSmXbF83D90(代码也在本文末尾)

我有一个原型函数(通用)和另一个扩展这个原型(特定)的函数。在通用原型中,我有一个数据对象。我希望特定对象使用此数据对象作为其自己的原型数据对象数据的基础,并将键添加到此数据对象而不是创建新的数据对象(这是我认为它正在做的事情)。

普兰克应该说明我的意思。

有人可以告诉我,我缺少哪些原型魔法来具体检查数据祖先的属性而不是(就像它似乎那样)在自己的原型中创建一个新的数据对象?

<script>
  function genericDataObject ( dataObject ) {
    if( !dataObject ) {
      this.data = {};
    } else {
      this.loadDataObject(dataObject);
    }
  }

  genericDataObject.prototype = {
    //want all data objects to have the alwayshere property
    data: {alwayshere: null},
    loadDataObject:  function (dataObject) {
      //if our dataObject has a key that is set to null in data then replace null with that key's value
      for (var key in dataObject) {
        if( this.data[key] === null) {
          this.data[key] = dataObject[key];
        }
      }
    }
  }

  function specificDataObject ( dataObject ) {
    genericDataObject.call(this, dataObject );
  }
  specificDataObject.prototype = new genericDataObject();
  //add specific properties, shouldn't data be instantiated here with alwayshere as we've called new genericDataObject()????
  specificDataObject.prototype.data.specificData1 = null;
  specificDataObject.prototype.data.specificData2 = null;  

  var genericObject = new genericDataObject( { alwayshere: "here it is"}  );
  var specificObject = new specificDataObject( {alwayshere: "where is it?", specificData1: "this works"});

  document.write( genericObject.data.alwayshere + "<br />"); //"here it is"
  document.write( specificObject.data.alwayshere + "<br />" );// undefined
  document.write( specificObject.data.specificData1);// "this works"

</script>

1 个答案:

答案 0 :(得分:1)

您将需要为每个实例创建一个新的data对象,否则所有实例将共享同一个对象(从原型继承到所有对象),并对此进行修改对象将影响所有实例。

你的对象之间的关系非常混乱:

genericObject: {} // empty!!!
 - inherits .data (and other properties) from genericDataObject.prototype

specificObject: {} // empty!!!
 - inherits .data (and other properties) from specificDataObject.prototype

genericDataObject.prototype: {data:…, loadDataObject:…}
 - inherits from Object.prototype

genericDataObject.prototype.data: {alwayshere: "here it is"}
 - inherits from Object.prototype
 - created as {alwayshere: null} in prototype literal
 - assigned "here it is" in genericObject.loadDataObject(…) //!!!

specificDataObject.prototype: {data:…}
 - inherits from genericDataObject.prototype
 - created by `new genericDataObject();`

specificDataObject.prototype.data:{specificData1:"this works",specificData2:null}
 - inherits from Object.prototype //!!!
 - created as {} in the genericDataObject constructor
 - assigned specificData1:null, specificData2:null explicitly
 - did *not* assign alwayshere:"where is it?" in specificObject.loadDataObject(…)
   because .alwayshere was not `null` - the property does not exists //!!!
 - did assign specificData1:"this works" in specificObject.loadDataObject(…)//!!!

如您所见,只有两个data个对象以某种方式积累了所有属性。并且一个不继承另一个 - 只有两个.prototype对象确实具有原型关系。这不是你想要的。

相反,你应该这样做:

function genericDataObject ( dataObject ) {
  this.data = Object.create(this.data);
  if (dataObject) {
    this.loadDataObject(dataObject);
  }
}

genericDataObject.prototype.data = {alwayshere: null};
genericDataObject.prototype.loadDataObject = function (dataObject) {
  // *only* if our dataObject has a key that is set to null in data then replace null with that key's value
  for (var key in dataObject) {
    if( this.data[key] === null) {
      this.data[key] = dataObject[key];
    }
  }
};

function specificDataObject(dataObject) {
  genericDataObject.call(this, dataObject);
}
specificDataObject.prototype = Object.create(genericDataObject.prototype);
specificDataObject.prototype.data = Object.create(genericDataObject.prototype.data);
specificDataObject.prototype.data.specificData1 = null;
specificDataObject.prototype.data.specificData2 = null;