您的位置:首页 > Web前端 > JavaScript

JavaScript 对象 之继承对象 学习笔记

2016-01-13 22:41 639 查看
      

  

  假设,我们有个这样的需求:

  两个种族,每个种族都有 名字、血量(默认200)、行为(行为有 跳跃、移动速度 这些属性)等共有属性。

  人族能量值比兽人多10%,兽人血量比人族多10%。

  职业有战士和法师两个职业,战士和法师有不一样的能量条:战士的为 怒气值(默认100),法师的为法力值(默认150)。战士有个自带的技能,为 攻击,法师有个自带的技能,为魔法攻击。这两个都属于 行为的属性。

  因为我们已经学过对象的创建,我们可以很轻松的写下如下代码

function HumanWarrior(name) {
this.name = name ;
this.race = "Human" ;
this.profess = "Warrior" ;
this.health = 200 ;
this.action = ["attack","jump","movespeed"] ;
this.power = 110 ;
}

function HumanMage(name) {
this.name = name ;
this.race = "Human" ;
this.profess = "Mage" ;
this.health = 200 ;
this.action = ["magic","jump","movespeed"] ;
this.mage = 165 ;
}

function OrcWarrior(name) {
this.name = name ;
this.race = "Orc" ;
this.profess = "Warrior" ;
this.health = 220 ;
this.action = ["attack","jump","movespeed"] ;
this.power = 100 ;
}

function OrcMage(name) {
this.name = name ;
this.race = "Orc" ;
this.profess = "Mage" ;
this.health = 220 ;
this.action = ["magic","jump","movespeed"] ;
this.mage = 150 ;
}

var player1 = new HumanWarrior("Heroic") ;
var player2 = new HumanMage("Wizard") ;
var player3 = new OrcWarrior("Brave") ;
var player4 = new OrcMage("Warlock") ;


  上面的代码,几乎给每个种族的每种职业都添加了构造函数,造成了很多的重复。所以我们试着给来个继承。

一、原型链

  利用原型让一个引用类型继承另一个引用类型的属性和方法。

function Person() {
this.health = 200 ;
this.power = 100 ;
this.action = ['jump','movespeed'] ;
}
// 初始化,给每个玩家初始化血量和技能。
Person.prototype.init = function () {
this.health = parseInt(this.health * this.healthtimes);
this.power = parseInt(this.power * this.powertimes);
if (this.profess === "Warrior") {
this.action.push("attack");
}else {
this.action.push("magic");
this.mage = this.power;
this.power = null;
}
}
function Human(name,profess) {
this.name = name ;
this.profess = profess;
this.race = "Human" ;
this.healthtimes = 1;
this.powertimes = 1.1;
}
function Orc(name,profess) {
this.name = name ;
this.profess = profess;
this.race = "Orc" ;
this.healthtimes = 1.1;
this.powertimes = 1;
}
Human.prototype = new Person();
Orc.prototype = new Person();

var player1 = new Human("Heroic","Warrior") ;
var player2 = new Human("Wizard","Mage") ;
var player3 = new Orc("Brave","Warrior") ;
var player4 = new Orc("Warlock","Mage");
// 初始化
player1.init() ;
player2.init() ;
player3.init() ;
player4.init() ;


  这里有个很严重的问题。所有 Human的实例 和 Orc的实例 都会共享一个 action。 结果就是player1,player2 的 action 是一样的, player3,player4 的 action 也是一样的。这是原型链的一个缺陷,我们可以采用另一个方法去解决这个问题。

二、借用构造函数

  在子类型构造函数的内部调用超类型构造函数。

function Person(name) {
this.name = name ;
this.health = 200 ;
this.power = 100 ;
this.action = ["jump","movespeed"] ;
}
Person.prototype.init = function () {

}
function Warrior() {
this.action.push("attack");
this.health = parseInt(this.health * this.healthtimes);
this.power = parseInt(this.power * this.powertimes);
}
function Mage() {
this.action.push("Magic");
this.health = parseInt(this.health * this.healthtimes);
this.power = parseInt(this.power * this.powertimes);
this.mage = this.power;
this.power = null;
}
function Human(name,profess) {
Person.call(this,name,profess) ;
this.race = "Human" ;
this.healthtimes = 1;
this.powertimes = 1.1;
if (profess == "Warrior") {
Warrior.call(this);
}else{
Mage.call(this);
}
}
function Orc(name,profess) {
Person.call(this,name) ;
this.profess = profess ;
this.race = "Orc" ;
this.healthtimes = 1.1;
this.powertimes = 1;
if (profess == "Warrior") {
Warrior.call(this);
}else{
Mage.call(this);
}
}

var player1 = new Human("Heroic","Warrior") ;
var player2 = new Human("Wizard","Mage") ;
var player3 = new Orc("Brave","Warrior") ;
var player4 = new Orc("Warlock","Mage") ;

//    错误 无法初始化,无法调用原型的方法了。
//    player1.init() ;


  该方法确实让 每个玩家都拥有了属于自己的 action,但是依然出现了另一种问题。那就是 没办法调用 Person() 的方法了,只能在子类上另写方法了,谈不上方法的复用了。

三、组合继承(伪经典继承)

  集 原型链 和 借用构造函数 的技术组合成一块,发挥二者之长的一种继承模式。

function Person(name) {
this.name = name ;
this.health = 200 ;
this.power = 100 ;
this.action = ["jump","movespeed"] ;
}
Person.prototype.show = function () {
var s = "name:" + this.name + "; Health:" + this.health + "; action:" + this.action.join(",");
alert(s);
}
function Warrior() {
this.action.push("attack");
this.health = parseInt(this.health * this.healthtimes);
this.power = parseInt(this.power * this.powertimes);
}
function Mage() {
this.action.push("Magic");
this.health = parseInt(this.health * this.healthtimes);
this.power = parseInt(this.power * this.powertimes);
this.mage = this.power;
this.power = null;
}
function Human(name,profess) {
//继承属性
Person.call(this,name,profess) ;
this.race = "Human" ;
this.healthtimes = 1;
this.powertimes = 1.1;
if (profess == "Warrior") {
//继承属性
Warrior.call(this);
}else{
//继承属性
Mage.call(this);
}
}
function Orc(name,profess) {
//继承属性
Person.call(this,name) ;
this.profess = profess ;
this.race = "Orc" ;
this.healthtimes = 1.1;
this.powertimes = 1;
if (profess == "Warrior") {
//继承属性
Warrior.call(this);
}else{
//继承属性
Mage.call(this);
}
}
//继承方法
Human.prototype = new Person();
Orc.prototype = new Person();

var player1 = new Human("Heroic","Warrior") ;
var player2 = new Human("Wizard","Mage") ;
var player3 = new Orc("Brave","Warrior") ;
var player4 = new Orc("Warlock","Mage") ;


  非常完美!无论是属性还是方法,都已经完美的继承了他们的父类。

  组合继承 避免了 原型链 和 构造函数 的缺陷,又融合了他们的优点,成为 JavaScript 中最常用的继承模式!

四、原型式继承

五、寄生式继承

六、寄生组合式继承
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: