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 中最常用的继承模式!
四、原型式继承
五、寄生式继承
六、寄生组合式继承
相关文章推荐
- 异步加载 js
- JavaScript2
- JavaScript思维导图
- JS_语句
- JTextArea中添加了JScrollPane后不显示滚动条
- JS截取字符串常用方法详细整理
- Jsoup的select选择器
- js中substr,substring,indexOf,lastIndexOf,split 的用法
- 抽出json数据组合成新的json
- javascript学习笔记三
- JavaScript:理解stringify
- JavaScript:理解parse
- wince 能用的 Newtonsoft.Json(Json.Net)
- JavaScript:理解toFixed
- JSESSIONID、SESSION、cookie .
- [javascript]页面显示动态时间
- js的闭包--匿名函数的使用
- js提示邮件地址功能
- Web Essentials之JavaScript,TypeScript和CoffeeScript
- Js 日期 多少分钟前,多少秒前