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 ...
随机推荐
- reverse-XNUCA-babyfuscator
上一次线上赛的一道题目 链接:http://pan.baidu.com/s/1qY9ztKC 密码:xlr2 这是一道代码混淆的题目,因为当时还不知道angr这样一个软件,所以我就用了自己的一种思路 ...
- Python 字符串关键字过滤
问题:把给定字符串中的关键字用与关键字等长的“*”串代替. Solution: 方法1: string 中的 replace 函数 方法2: def censor(text, word): words ...
- 实际项目中积累的一些关于事件的简单应用JS代码段(能力有限,不喜轻喷,23333)
1:鼠标移入移出显示另一张图片 var yuanquan_1 = document.getElementById("yuanquan_1" ); yuanquan_1. onmo ...
- NSFetchedResultsControllerDelegate不执行
熬了2 ,3个小时 才解决这个问题 在进行IM 设置时候 NSFetchRequest *request=[NSFetchRequest fetchRequestWithEntityName:@&q ...
- POJ 2533 动态规划入门 (LIS)
Longest Ordered Subsequence Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42914 Accepte ...
- // 开始无限播放 ViewPager
public class MainActivity extends Activity { private ViewPager vp; private Handler handler = new ...
- passing argument 3 of ‘wtk_hlv_rec_init’ discards ‘const’ qualifier from pointer target type
-Werror,编译出现如下错误: src/wtk/exam/wtk_ndx.c:154:6: error: passing argument 3 of ‘wtk_hlv_rec_init’ disc ...
- weave
Docker的原生网络支持非常有限,且没有跨主机的集群网络方案.目前实现Docker网络的开源方案有Weave.Kubernetes.Flannel.Pipework以及SocketPlane等,其中 ...
- Openstack Neutron L2 Population
Why do we need it, whatever it is? VM unicast, multicast and broadcast traffic flow is detailed in m ...
- Windows性能查看器:系统的性能信息(I/O,IIS最大连接数,Sql) ,以及解决 asp.net IIS 一二百多用户并发
在测试过程中,我们经常需要知道“系统的资源利用情况”来监测我们的测试执行情况,来查看测试环境是否有效,测试结果是否可信,或者是在无人值守时保存结果,等我们值班时再来分析. 1.在Windows环境下, ...