2016-05-27 218 views
1

我通過一個問題與JavaScript的繼承的幾個方面的實驗,我碰到:的Javascript原型繼承

創建預約系統,圖書航班座位或酒店客房。它針對飛機或旅館的特定部分收取各種費用。例如,頭等艙的成本將比教練高。酒店房間有複式套房,價格更高。跟蹤房間什麼時候可用並且可以安排。

我正在處理酒店房間問題。

我決定帶一個房間基礎對象與一個名爲'duration'的數據成員一起記錄房間預訂的天數,以及兩種方法:預訂和結帳。

我有一個繼承自SingleRoom的派生對象'SingleRoom'。

下面的代碼:

function Room(duration){ 
    this.duration = duration; 
} 
Room.prototype.book =()=>{ 
    if (this.prototype.count > 0){ 
     this.prototype.count -= 1; 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

Room.prototype.checkOut =()=>{ 
    this.prototype.count += 1; 
    console.log("Room checked out"); 
} 

function SingleRoom(duration){ 
    this.price = 1000; 
} 
SingleRoom.prototype = new Room(); 
SingleRoom.prototype.constructor = SingleRoom; 
SingleRoom.prototype.count = 3; 
var sr1 = new SingleRoom(2); 
if(sr1.book() === false){ 
    console.log("Could not book room"); 
} 

我得到的「this.prototype.count」以下錯誤:無法讀取的不確定

任何想法,問題是財產計數?

謝謝!

+0

'this.count'?爲什麼你要在子類中定義count,但是在超類方法中使用它呢? – Oriol

+0

您不使用'this.prototype。*'來訪問原型屬性。 – zzzzBov

+0

SingleRoom是從SingleRoom繼承嗎? – leaf

回答

3

您應該只對構造函數使用prototype屬性。這是正確的:

SingleRoom.prototype = new Room(); 
SingleRoom.prototype.constructor = SingleRoom; 
SingleRoom.prototype.count = 3; 

但是,您不應該在單個對象上使用它。當您訪問未在直接對象上定義的屬性時,將自動搜索原型鏈。無論你有this.prototype.count更改爲this.count,它會正常工作。

+0

'SingleRoom.prototype = new Room();'是一種反模式,一般而言,也是因爲'Room'需要一個參數。它應該是SingleRoom.prototype = Object.create(Room.prototype);'然後'SingleRoom'在施工期間調用'Room':'Room.call(this,duration);' –

2

你正在混淆函數與實例(或者至少,你使用函數的屬性和你在實例中使用的函數;這很容易做真的)。 prototype屬性用於構造函數。它指向將被分配爲通過該構造函數創建的對象的基礎原型(在規範中稱爲[[Prototype]])的原型對象。它不是(令人困惑地)提到一個對象的原型;爲了得到這個(規範稱爲[[Prototype]]的東西),你使用Object.getPrototypeOf(theObject),但它是相對罕見的你想要的。

這可能有助於澄清關係:

function Thing(name) { 
 
    this.name = name; 
 
} 
 
Thing.prototype.say = function() { 
 
    console.log(this.name); 
 
}; 
 
var t = new Thing("Ben"); 
 
console.log(t.prototype);  // undefined, `t` has no `prototype` property 
 
console.log(Thing.prototype); // an object with `say` 
 
t.say();      // "Ben" 
 
console.log(Object.getPrototypeOf(t) === Thing.prototype); // true

的另一個問題是,你使用箭頭的功能來定義的原型功能,這將無法正常工作;箭頭函數的關鍵在於它們關閉了this,但對於原型函數,您希望this通過函數的調用方式進行設置。

如果您使用的是ES2015(例如,使用Babel或類似方式進行轉譯),則可以使用漂亮,新穎,簡單的語法。我不得不猜測count應該是什麼;我把它放在Room實例:

class Room { 
    constructor(duration){ 
     this.duration = duration; 
     this.count = 3; 
    } 

    book() { 
     if (this.count > 0) { 
      this.count -= 1; 
      return true; 
     } 
     else { 
      return false; 
     } 
    } 

    checkOut() { 
     this.count += 1; 
     console.log("Room checked out"); 
    } 
} 

class SingleRoom extends Room { 
    constructor(duration){ 
     super(duration); 
     this.price = 1000; 
    } 
} 

var sr1 = new SingleRoom(2); 
if (sr1.book() === false){ 
    console.log("Could not book room"); 
} 

如果你想使用ES5,這裏是與筆記翻譯:

function Room(duration) { 
    this.duration = duration; 
    this.count = 3; 
} 
// Note we *don't* use arrow functions for prototype functions; it's important 
// for them to get `this` by how they're called. 
Room.prototype.book = function() { 
    if (this.count > 0) { 
     this.count -= 1; 
     return true; 
    } 
    else { 
     return false; 
    } 
}; 
Room.prototype.checkOut = function() { 
    this.count += 1; 
    console.log("Room checked out"); 
}; 

// Derive SingleRoom from Room 
function SingleRoom(duration) { 
    Room.call(this, duration); // Necessary to init Room 
    this.price = 1000; 
} 
SingleRoom.prototype = Object.create(Room.prototype); // NOT `new Room()` 
SingleRoom.prototype.constructor = SingleRoom; 

var sr1 = new SingleRoom(2); 
if (sr1.book() === false){ 
    console.log("Could not book room"); 
}