2016-05-27 184 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"); 
}