组合继承

  组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方 法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数 复用,又能够保证每个实例都有它自己的属性。下面来看一个例子:

  

   <script>
function Person(name, age, friends) {
this.name = name;
this.age = age;
this.friends = ["Carol", "Seylia"];
if (typeof this.ShowPerson != "function") {
this.ShowPerson = function () {
var message = "name:" + this.name + "\n\rage:" + this.age + "\r\nfriends:";
this.friends.forEach(function (value, index, arr) {
message += " " + value;
});
alert(message);
}
}
} function Student(name, age, job) {
Person.call(this, name, age);
this.job = job;
} //这里继承了
Student.prototype = new Person();
Student.prototype.constructor = Student; var s1 = new Student("gck", , "Sf");
s1.friends.push("Core");
s1.ShowPerson(); var s2 = new Student("Carol", , "Sf");
s2.ShowPerson();
</script>

组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript中常用的继 承模式。而且,instanceof 和 isPrototypeOf()也能够用于识别基于组合继承创建的对象.

  注:不准备说原型链和借用构造,因为这两个缺陷太大,不过有想了解的可以查一下。

寄生组合式继承

面说过,组合继承是 JavaScript 常用的继承模式;不过,它也有自己的不足。组合继承大的 问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是 在子类型构造函数内部。没错,子类型终会包含超类型对象的全部实例属性,但我们不得不在调用子 类型构造函数时重写这些属性,所以我用寄生组合继承:

  所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背 后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型 原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型 的原型。寄生组合式继承的基本模式如下所示。

<script>
//如果Object.create浏览器不支持,则用这个方法代替
function object(o) {
function F() { }
F.prototype = o;
return new F();
} function inheritPrototype(subType, superType) { //创建对象
var prototype = Object.create(superType.prototype);//这个方法IE9+才支持
//var prototype = object(superType.prototype); //增强对象
prototype.constructor = subType; //指定对象
subType.prototype = prototype; } function Person(name, age, friends) {
this.name = name;
this.age = age;
this.friends = ["Carol", "Seylia"];
if (typeof this.ShowPerson != "function") {
this.ShowPerson = function () {
var message = "name:" + this.name + "\n\rage:" + this.age + "\r\nfriends:";
this.friends.forEach(function (value, index, arr) {
message += " " + value;
});
alert(message);
}
}
} function Student(name, age, job) {
Person.call(this, name, age);
this.job = job;
} //这里继承了
inheritPrototype(Student, Person); var s1 = new Student("gck", 26, "Sf");
s1.friends.push("Core");
s1.ShowPerson(); var s2 = new Student("Carol", 28, "Sf");
s2.ShowPerson(); </script>

这个例子的高效率体现在它只调用了一次Person构造函数,并且因此避免了在 Student. prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf()。开发人员普遍认为寄生组合式继承是引用类型理想的继承范式。
YUI

【JavaScript回顾】继承的更多相关文章

  1. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

  2. Javascript模拟继承(赠送.net吐槽一段)

    首先吐槽一句,今年的就业形势很不乐观啊,特别是搞.net的(相对java),特特别是还没出校门没有正式工作经验的,找个实习很难,前些天接了个面试电话,上来就质疑我“你一个在校大学生怎么可能做了那么多项 ...

  3. 详解Javascript的继承实现(二)

    上文<详解Javascript的继承实现>介绍了一个通用的继承库,基于该库,可以快速构建带继承关系和静态成员的javascript类,好使用也好理解,额外的好处是,如果所有类都用这种库来构 ...

  4. javascript深度克隆与javascript的继承实现

    1.javascript深度克隆: //注意这里的对象包括object和array function cloneObject(obj){ var o = obj.constructor === Arr ...

  5. 再谈javascript原型继承

    Javascript原型继承是一个被说烂掉了的话题,但是自己对于这个问题一直没有彻底理解,今天花了点时间又看了一遍<Javascript模式>中关于原型实现继承的几种方法,下面来一一说明下 ...

  6. TDD测试驱动的javascript开发(3) ------ javascript的继承

    说起面向对象,人们就会想到继承,常见的继承分为2种:接口继承和实现继承.接口继承只继承方法签名,实现继承则继承实际的方法. 由于函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承. ...

  7. 彻底理解Javascript原型继承

    彻底理解Javascript原型继承 之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入. 本文试图进一步思考,争取彻底理解Javascript继承原理 实例成员 ...

  8. Javascript原型继承容易忽略的错误

    编写Javascript的开发者都知道,JS虽然没有类(ES6添加了class语法),但是可以模拟出OOP语言的类和面向对象的概念,比如我们都知道的一句话,Javascript中处处是对象,而面向对象 ...

  9. JavaScript类继承, 用什么方法好

    JavaScript类继承, 用什么方法好 一个实例: 基类Car: function Car(color, year) { this.name = "car"; this.col ...

  10. [转]Javascript原型继承

    真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承.Javascript原型继承是一个被说烂掉了的话题 ...

随机推荐

  1. Visual Studio 2010配置OpenGL-1.8

    参考博客 : 安装参考 1. http://blog.csdn.net/mooncircle/article/details/5545448 2. http://www.cnblogs.com/moo ...

  2. C#代理那点事儿

    Func代理是啥? Func代理接收0个或多个参数,返回TResult值: 以Func<TSource, TResult>为例:Func带来封装一个方法,该方法接收一个参数,然会一个TRe ...

  3. No Assistant Results

    由于修改一些文件名字等会导致这个不工作. "Organizer" / "Projects" / 选择你的项目.  "Delete" .

  4. 深圳测试研讨会圆满结束,PPT共享

    深圳测试研讨会圆满结束,PPT共享http://www.automationqa.com/forum.php?mod=viewthread&tid=3417&fromuid=29

  5. 架构模式之REST架构

    直至今日,分布式系统(Distributed System)已经取得了大规模的应用,特别是Web的发展,已经给软件开发带来了翻天覆地的变化,这一点已经毋庸置疑了. 构建分布式系统常用的技术通常就是使用 ...

  6. Android之线程回掉更新ui

    一:工作线程中的回掉更新UI public class MainActivity extends AppCompatActivity { private int i; private Callback ...

  7. Unix sed实用教程系列目录[已完成]

    本系列文章已经译完了,译自awk-sed@theunixschool,收获颇丰,作者没有讲明白的我做了补充,并且尝试讲的更清楚,整理成系列索引,方便学习,开篇非译文,是我为了方便后面的理解写的一篇,感 ...

  8. Linux系统下安装rz/sz命令及使用说明

    对于经常使用Linux系统的人员来说,少不了将本地的文件上传到服务器或者从服务器上下载文件到本地,rz / sz命令很方便的帮我们实现了这个功能,但是很多Linux系统初始并没有这两个命令.今天,我们 ...

  9. Ciel and Robot

    C. Ciel and Robot time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  10. Android源码下载并绑定到Eclipse中

    在Windows下,通过SDK Manager.exe更新下载的Android,是不带源码的,我们开发开发起来不是很方便: 其实Android的源代码是可以下载的,其源代码入在http://andro ...