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

  两个种族,每个种族都有 名字、血量(默认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 对象 之继承对象 学习笔记的更多相关文章

  1. 《JavaScript DOM 编程艺术》 学习笔记

    目录 <JavaScript DOM 编程艺术> 学习笔记 第一章 js简史 第二章 js语法 准备工作 语法 第三章 DOM DOM中的D DOM中的O DOM中的M 第四章 js图片库 ...

  2. 【JavaScript】类继承(对象冒充)和原型继承__深入理解原型和原型链

    JavaScript里的继承方式在很多书上分了很多类型和实现方式,大体上就是两种:类继承(对象冒充)和原型继承. 类继承(对象冒充):在函数内部定义自身的属性的方法,子类继承时,用call或apply ...

  3. .NET 云原生架构师训练营(对象过程建模)--学习笔记

    目录 UML OPM OPM优化 UML 1997年发布UML标准 主要域 视图 图 主要概念 结构 静态视图 类图 类.关联.泛化.依赖关系.实现.接口 用例视图 用例图 用例.参与者.关联.扩展. ...

  4. Java中对象的比较(学习笔记)

    1)详细说明对象的比较方式有哪些? ①对象引用的比较("= ="运算符) "= ="是将对象的引用进行比较,实质是比较两个引用变量是否引用同一个对象.注意的点: ...

  5. JavaScript闭包(Closure)学习笔记

    闭包(closure)是JavaScript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于JavaScript初学者应该是很有用的. 一.变量的作用域 要理解 ...

  6. 《JavaScript DOM编程艺术》学习笔记(一)

    这本书是我听说学习前端基础入门书籍,于是就开始看了,大概是从5月10号开始看的吧,一直看到现在,差不多要看完了,书是挺厚的...286页,不过比起JAVASCRIPT权威指南来说还是差多了,权威指南才 ...

  7. JavaScript权威设计--JavaScript类型,值,变量(简要学习笔记三)

    1.负号是一元求反运算 如果直接给数字直接量前面添加负号可以得到他们的负值     2.JavaScript中的运算超出了最大能表示的值不会报错,会显示Infinity. 超出最小也不报错,会显示-I ...

  8. Javascript垃圾回收机制(学习笔记)

    1,javascript具有自动的垃圾回收机制,自动内存的分配和无用内存的回收都可以自动管理.垃圾回收器周期性的执行: 2,Javascript的垃圾回收策略分为:引用计数和标记清除: 2.1 标记清 ...

  9. JavaScript原型与原型链学习笔记

    一.什么是原型?原型是一个对象,其他对象可以通过它实现属性继承.简单的说就是任何一个对象都可以成为原型 prototype属性: 我们创建的每个函数都有一个prototype属性,这个属性是一个指针, ...

  10. JavaScript权威设计--CSS(简要学习笔记十六)

    1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domai ...

随机推荐

  1. js 网站顶部导航栏

    (function(){ var map = { 'index' : 0, 'gift_code' : 1, 'base_info' : 1, 'band_phone': 1, 'unlink_pho ...

  2. IOS7 ~ Xcode5 制作 framework

    一.Framework 简介(Introduction to Framework Programming Guide) Mac OS X 扩展了 framework 的功能,让我们能够利用它来共享代码 ...

  3. js常见函数汇总

    /**  * 隐藏元素  * @param {String} elem  */ function hide(elem){     var curDisplay = getStyle(elem, 'di ...

  4. Sublime Text 快捷键及插件安装

    Sublime Text是一款跨平台的编辑器,它小巧绿色且速度非常快,支持各种流行编程语言的语法高亮.代码补全等,插件非常丰富!editplus.notepad++也都是不错的工具,体积轻巧,启动迅速 ...

  5. Java:String和Date、Timestamp之间的转换

    一.String与Date(java.util.Date)互转 1.1 String -> Date String dateStr = "2016-9-28 12:25:55" ...

  6. oracle日期操作

    日期操作:ADD_MONTHS(date,i) 作用 返回在自定日期上添加的月份 i是整数 如果i是小数,则截取整数部分 i是负数 原有日期减去相应部分 例子: SQL> select add_ ...

  7. StatisticalOutlierRemoval源码

    源代码 * * Software License Agreement (BSD License) * * Point Cloud Library (PCL) - www.pointclouds.org ...

  8. iwork 09 可以用的序列号

    E4RJ-YKHP-9ER4-WK9Y-H4UM-5S2G9MU-9U9J-KN4M-4PAE-DYNA-5S2EGMU-3PKP-NN9G-3JW4-3RAD-5S2

  9. 反编译dtsi

    dtsi机制是linux kernel为了适配多设备做出来的模块,产品线拉的较长的话用它来控制最合适不过了.初步阅读了下代码和接口清晰简洁. 这个东东出来的时候xml/json应该比较成熟了,疑惑的是 ...

  10. windows环境下,如何启动chromedriver

    java -jar selenium-server-standalone-2.41.0.jar -Dwebdriver.chrome.driver="C:\Program Files\Goo ...