JavaScript 对象 之继承对象 学习笔记
假设,我们有个这样的需求:
两个种族,每个种族都有 名字、血量(默认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 中最常用的继承模式!
四、原型式继承
五、寄生式继承
六、寄生组合式继承
JavaScript 对象 之继承对象 学习笔记的更多相关文章
- 《JavaScript DOM 编程艺术》 学习笔记
目录 <JavaScript DOM 编程艺术> 学习笔记 第一章 js简史 第二章 js语法 准备工作 语法 第三章 DOM DOM中的D DOM中的O DOM中的M 第四章 js图片库 ...
- 【JavaScript】类继承(对象冒充)和原型继承__深入理解原型和原型链
JavaScript里的继承方式在很多书上分了很多类型和实现方式,大体上就是两种:类继承(对象冒充)和原型继承. 类继承(对象冒充):在函数内部定义自身的属性的方法,子类继承时,用call或apply ...
- .NET 云原生架构师训练营(对象过程建模)--学习笔记
目录 UML OPM OPM优化 UML 1997年发布UML标准 主要域 视图 图 主要概念 结构 静态视图 类图 类.关联.泛化.依赖关系.实现.接口 用例视图 用例图 用例.参与者.关联.扩展. ...
- Java中对象的比较(学习笔记)
1)详细说明对象的比较方式有哪些? ①对象引用的比较("= ="运算符) "= ="是将对象的引用进行比较,实质是比较两个引用变量是否引用同一个对象.注意的点: ...
- JavaScript闭包(Closure)学习笔记
闭包(closure)是JavaScript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于JavaScript初学者应该是很有用的. 一.变量的作用域 要理解 ...
- 《JavaScript DOM编程艺术》学习笔记(一)
这本书是我听说学习前端基础入门书籍,于是就开始看了,大概是从5月10号开始看的吧,一直看到现在,差不多要看完了,书是挺厚的...286页,不过比起JAVASCRIPT权威指南来说还是差多了,权威指南才 ...
- JavaScript权威设计--JavaScript类型,值,变量(简要学习笔记三)
1.负号是一元求反运算 如果直接给数字直接量前面添加负号可以得到他们的负值 2.JavaScript中的运算超出了最大能表示的值不会报错,会显示Infinity. 超出最小也不报错,会显示-I ...
- Javascript垃圾回收机制(学习笔记)
1,javascript具有自动的垃圾回收机制,自动内存的分配和无用内存的回收都可以自动管理.垃圾回收器周期性的执行: 2,Javascript的垃圾回收策略分为:引用计数和标记清除: 2.1 标记清 ...
- JavaScript原型与原型链学习笔记
一.什么是原型?原型是一个对象,其他对象可以通过它实现属性继承.简单的说就是任何一个对象都可以成为原型 prototype属性: 我们创建的每个函数都有一个prototype属性,这个属性是一个指针, ...
- JavaScript权威设计--CSS(简要学习笔记十六)
1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domai ...
随机推荐
- C#与XML Schema的问题
http://bbs.csdn.net/topics/50493564 weileily: 用XmlSchema.Read方法读取了一个xsd文件,请问如何遍历检索器中的ComplexType与Sim ...
- Android 学习第11课,android 实现拨打电话的功能
1. 先布局界面,界面采用线性垂直方式来布局 在layout 界面文件中 activity_main.xml 中 <LinearLayout xmlns:android="http:/ ...
- Spring总结
此君也是使用过多时了,却从来没有系统的总结过 以下,弥补,盼不晚: Spring为什么是框架&容器 1.框架的原因: 其提供多个组件的搭建,和支持其他事务事件,符合框架定义 ps:什么是框架呢 ...
- HDU 2277 Change the ball
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2277 Change the ball Time Limit: 2000/1000 MS (Java/O ...
- zoj3551 Bloodsucker ——概率DP
Link: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4530 A[i]数组表示当吸血鬼有 I 个的时候,还需要的天数.可以 ...
- LVS的调度算法
LVS的调度算法(Scheduling Method)一共有10种 一.静态方法:仅根据算法本身进行调度 1.rr(Round Robin):轮询 2.wrr(Werghted Round Robin ...
- 旅行家的预算 1999年NOIP全国联赛普及组NOIP全国联赛提高组
时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车 ...
- Extjs控制面板组件
(1)aoolyTo:(id) renderTo:(id)呈现在哪个html里面,同上 id最好用"" contentEI:() 呈现哪个html元素里面,把eI内的内容呈现 ( ...
- 关于 MAXScript 如何剪切文件夹
MAXScript 中可以对文件进行创建删除复制等操作但是唯独不能删除文件夹... 网上搜了一下批处理的剪切方法,在 MAXScript 里调用一下就好了 fn xcopy oldfile newfi ...
- CSS3 动画基础
该文为译文转载,原文地址:http://tech.163.com/mobile/10/0106/09/5SB96QSM00112K88.html 译文:你需要知道的CSS3 动画技术 原文:Wha ...