2017-10-19 228 views
1

如果我理解正確,object.hasOwnProperty()應該在父類的繼承屬性上返回false。但是,下面的代碼在自己的和繼承的屬性上都返回true。Typescript:object.hasOwnProperty()在繼承的屬性上顯示true。爲什麼?

我的理解/代碼不正確或者是hasOwnPropery()不正確? 如果是我,我如何區分自己的和遺傳的屬性?

編輯:我已將我的用例添加到示例代碼中。

我期望孩子的fromDb()只會照顧自己的屬性,而不是覆蓋父母的fromDb()設置的屬性。

class Parent { 
    parentProp = ''; 
    fromDb(row: {}) { 
     for (const key of Object.keys(row)) { 
      if (this.hasOwnProperty(key)) { 
       if (key === 'parentProp') { 
        // Do some required data cleansing 
        this[key] = row[key].toUpperCase() 
       } else { 
        this[key] = row[key]; 
       } 
      } 
     }; 
     return this; 
    } 
} 

class Child extends Parent { 
    childProp = ''; 
    fromDb(row: {}) { 
     super.fromDb(row); 
     for (const key of Object.keys(row)) { 
      if (this.hasOwnProperty(key)) { 
       this[key] = row[key]; 
      } 
     }; 
     return this; 
    } 
} 

let row = { 
    parentProp: 'parent', 
    childProp: 'child', 
} 

let childObj = new Child().fromDb(row); 
console.log(childObj); 

控制檯:

Child: 
    childProp: "child" 
    parentProp: "parent" 

回答

2

在生成的代碼extends,屬性將被複制到子類是這樣的:

function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 

這意味着你的子類(d)被賦予它自己的財產。

這實際上是用普通的JavaScript繼承沒有什麼不同:

function Parent() { 
    this.parentProp = `I'm defined by Parent`; 
} 

function Child() { 
    Parent.call(this); 
    this.childProp = `I'm defined by Child`; 
} 

let childObj = new Child(); 

for (const key of Object.keys(childObj)) { 
    console.log(key, childObj.hasOwnProperty(key)); 
} 

如果你給我們你需要達到什麼樣的一些方向,我相信我們會找到一個合適的機制,你的意志克服這個障礙。

具體使用案例

爲了您的具體使用情況,您可以通過設置在您調用父類的誰「贏」的先例。

爲了讓輸出

childProp: "child" 
parentProp: "PARENT" 

讓家長跑 「第二」,而不是 「第一」:

class Child extends Parent { 
    childProp = ''; 
    fromDb(row: {}) { 
     for (const key of Object.keys(row)) { 
      if (this.hasOwnProperty(key)) { 
       this[key] = row[key]; 
      } 
     }; 

     super.fromDb(row); // <-- last update wins 
     return this; 
    } 
} 

超級動態屬性的東西

這將動態地排除母密鑰從父子的子鍵和子鍵...添加console.log語句查看內部結構...

class Parent { 
    parentProp = ''; 
    fromDb(row: {}) { 

     const ownKeys = Object.keys(new Parent()); 

     for (const key of Object.keys(row)) { 
      if (ownKeys.indexOf(key) > -1) { 
       if (key === 'parentProp') { 
        // Do some required data cleansing 
        this[key] = row[key].toUpperCase() 
       } else { 
        this[key] = row[key]; 
       } 
      } 
     }; 
     return this; 
    } 
} 

class Child extends Parent { 
    childProp = ''; 
    fromDb(row: {}) { 
     super.fromDb(row); 

     const ownKeys = this.getKeys(); 

     for (const key of Object.keys(row)) { 
      if (ownKeys.indexOf(key) > -1) { 
       this[key] = row[key]; 
      } 
     }; 
     return this; 
    } 

    getKeys() { 
     const childKeys = Object.keys(this); 
     const parentKeys = Object.keys(new Parent()); 

     return childKeys.filter(function(el) { 
      return parentKeys.indexOf(el) < 0; 
     }); 
    } 
} 

let row = { 
    parentProp: 'parent', 
    childProp: 'child', 
} 

let childObj = new Child().fromDb(row); 
console.log(childObj); 
+0

我編輯了問題以包含我的用例。 – passerby

+0

我已經爲該特定用例添加了一些細節。如果你需要更具選擇性,你將不得不創建一個屬性映射,以便孩子看看地圖,而不是它自己的鍵(即「如果屬性在我的地圖中,我會改變它,否則我不會」 )。 – Fenton

+0

似乎複製發生在兩個方向。當我將'console.log(Object.keys(this))'添加到Parent的'fromDb()'時,它還顯示由'super.fromDb(row)'調用的Child的屬性。我從來沒有意識到語法糖的這種影響。天真的我... – passerby

0

類是好老的構造函數的語法只是語法糖。在類中定義屬性始終是編譯成在構造函數中設置的值實例屬性:

function Parent() { 
    this.parentProp = "I'm defined by Parent"; 
} 

酒店不從原型來了,它是一個實例屬性在構造上this設置。只有方法在原型上共享。如果你想共享屬性,他們必須聲明爲static;但是它們是類屬性,而不是原型。

+0

我想我必須調整我對OO的想法...... – passerby