与类的创建篇一样,这里先贴出最终代码,再做详细分析:

// 创建一个父类
function SuperType(){
this.company = 'alibaba';
} function SubType(){
SuperType.call(this); // 【1. 调用父类的构造函数】
this.name = 'yunos';
} SubType.prototype = Object.create(SuperType.prototype,{constructor:{value:SubType}}); // 【2. 把父类的原型赋给子类】
var instance = new SubType();
console.log(instance); /*----------------牢记两部关键性的操作,到此为止,已实现理想化的继承------------------------*/ var instance = new SubType();
instance instanceof SubType // true.
instance instanceof SuperType // true.

鉴于部分浏览器尚不支持Object.create, 修正后如下:

// 辅助函数,解决浏览器不支持Object.create的问题,同时正确指向构造函数
function createObject(proto, constructor) {
var newProto;
if (Object.create) {
newProto = Object.create(proto);
} else {
function Empty(){};
Empty.prototype = proto;
newProto = new Empty();
}
newProto.constructor = constructor;
return newProto;
} // 创建一个父类
function SuperType(){
this.company = 'alibaba';
}function SubType(){
SuperType.call(this); // 调用父类的构造函数.
this.name = 'yunos';
}
SubType.prototype = createObject(SuperType.prototype, SubType); // 把父类的原型赋给子类 var instance = new SubType();
instance instanceof SubType // true.
instance instanceof SuperType // true.

Javascript中最常用的继承模式: 原型链 + 借用构造函数 = 组合继承(又称伪经典继承)。

原型链继承:

function SuperType(){
this.company = 'alibaba';
}
SuperType.prototype.getSuperValue = function(){
return this.company;
} function SubType(){
this.name = 'yunos';
}
SubType.prototype = new SuperType(); var instance = new SubType();
console.log(instance);

众所周知,Javascript是通过prototype来实现继承的,在此我们创建父类的实例重写了 SubType.prototype。
换句话说,原来存在于 SuperType 的实例中的所有属性和方法现在也存在于 SubType.prototype中了。
如下所示:

当然,不要忘记最后一环,所有的引用类型默认都继承了Object,这一环也是通过原型链来实现的,所有函数默认的原型 { constructor : '...' }都是Object的实例。

尽管原型链如此强大,可以用它来实现继承,但在实践中我们很少这样做,因为它存在一个严重的问题:父类的属性会成为子类的原型属性,

而当原型属性包含引用类型值时,该原型属性会被类的所有实例共享,在一个实例上进行的修改,会影响到其他实例。

借用构造函数继承:

在解决原型中包含引用类型值多带来问题的过程中,使用一种叫做借用构造函数的技术(有时候也叫做伪造对象或经典继承)。 这种技术思想相当简单,即在子类型构造函数的内部调用父类的构造函数。  —— 函数只不过是在特定环境中执行代码的对象,因此通过使用apply 和 call 方法可以在新创建的对象上执行构造函数,如下所示:

function SuperType(){
this.colors = ["red", "blue", "green"];
} function SubType(){
SuperType.call(this); // 【借调父类的构造函数】
} var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); // red, blue, green, black" var instance2 = new SubType();
alert(instance2.colors); // "red, blue, green"

通过借调,我们实际上是在(未来将要)新创建的SubType 实例的环境下调用了 SuperType 构造函数。 这样,就会在新SubType对象上执行 SuperType() 函数中定义的所有对象初始化代码。 然后, SubType的每个实例就都会具有自己的 colors 属性的副本了。

而且它还具有一个很大的优势,即可以在子类构造函数中向父类的构造函数传递参数:

function SuperType(name){
this.name = name;
} function SubType(){
  SuperType.call(this, "yunos");
  this.age = 29;
} var instance = new SubType();
console.log(instance.name); // "yunos";
console.log(instance.age); //

为了确保父类构造函数不会重写子类型的属性,可以在调用父类构造函数后,再添加应该在子类型中定义的属性。

组合继承:

将原型链和借用构造函数的技术组合到一块,从而发挥二者之长,是当前应用最广泛的继承方法:

function SuperType(){
this.company = "alibaba";
}
SuperType.prototype.getSuperValue = function(){
return this.company;
} function SubType(){
  SuperType.call(this); // 【借调父类的构造函数】
  this.name = "yunos";
}
SubType.prototype = new SuperType(); var instance1 = new SubType();
console.log(instance1);

虽然并不完美,但类的功能终于具备了,无明显弊端,使用方法也比较简单,所以被广泛使用。

至此本文应该结束了,但严谨的,偏执的,追求完美的程序员,一直在探求更为完美的实现方式,于是便有了下边的内容:

Javascript中最理想的继承范式: 原型式 —> 寄生式 —> 寄生组合式继承(广泛应用于YUI、KISSY中)—> 最终继承

// 辅助方法,用以正确继承父类原型
function inheritPrototype(subType, superType){
function F(){};
F.prototype = superType.prototype;
var protoObj = new F(); }

Javascript面向对象之继承的更多相关文章

  1. JavaScript面向对象(三)——继承与闭包、JS实现继承的三种方式

      前  言 JRedu 在之前的两篇博客中,我们详细探讨了JavaScript OOP中的各种知识点(JS OOP基础与JS 中This指向详解 . 成员属性.静态属性.原型属性与JS原型链).今天 ...

  2. Javascript 面向对象编程—继承和封装

      前  言 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类) ...

  3. javascript面向对象中继承实现?

    面向对象的基本特征有:封闭.继承.多态. 在javascript中实现继承的方法: 1.原型链(prototype chaining) 2.call()/apply() 3.混合方式(prototyp ...

  4. 【前端学习】javascript面向对象编程(继承和复用)

    前言       继承,代码复用的一种模式.和其它高级程序语言相比,javascript有点点不一样,它是一门纯面向对象的语言,在JS中,没有类的概念,但也可以通过原型(prototype)来模拟对象 ...

  5. javascript 面向对象的继承的实现

    JavaScript 中的面向对象的初步认识 上面这篇简单的记录了我对 JS面向对象实现的一点初步认识和了解,下面继续研究JS面向对象,实现继承和多态. 之前的学习我了解到了 :构造函数加属性,原型p ...

  6. javascript面向对象:继承、多态

    继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属性),同时可扩展自己的成员,下面介绍几种js中实现继承的方式: 1,对象模仿:通过动态的改变 this 指针的指向,实现 ...

  7. javascript面向对象事件继承

    继承:父类有的,子类也有.父类改变,子类也跟着变. 属性继承:      矫正this (window对象,矫正成object对象)     fn .call(this是谁,参数1,参数2...); ...

  8. Javascript 面向对象之继承

    本文参考书籍<<Javascript高级程序设计>> js继承方式:实现继承,主要依靠原型链实现. 原型链:基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法. 这 ...

  9. javascript 面向对象(实现继承的几种方式)

     1.原型链继承 核心: 将父类的实例作为子类的原型 缺点:  父类新增原型方法/原型属性,子类都能访问到,父类一变其它的都变了 function Person (name) { this.name ...

随机推荐

  1. go语言实现一个简单的登录注册web小程序

    最近学习golang也有一段时间了,基础差不多学了个大概,因为本人是java程序员,所以对web更感兴趣.根据<go web编程>中的例子改编一个更简单的例子,供新手参考,废话不多说,上菜 ...

  2. [转]office2010一直卡在“正在受保护的视图中打开”

    用Office 2010 打开文件遇到“”,如下图: 转自: 解决办法: 还可以使用下面的方法打开上图的受保护视图设置界面:   1. 启动 Word 2010 应用程序,单击[文件]按钮并选择[选项 ...

  3. Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法

    一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...

  4. 在cxf中使用配置避免增加字段导致客户端必须更新、同步实体属性的问题

    在使用cxf实现webservice时,经常碰到的问题就是如果在服务端,修改了一个接口的签名实现,如增加一个字段,或者删除一个字段.在这种情况下,在默认的配置中,就会报以下的错误信息: org.apa ...

  5. Android composite adb interface

    我的平板连上电脑后,在eclipse的DDMS中查看不到.很奇怪以前不会,我以为在进程中有其他的adb.exe冲突.查看任务管理器没有看到其他adb.exe进程.然后重启eclipse也不用,重启电脑 ...

  6. 使用commons-beanutils迭代获取javabean的属性

    NoteEntity entity = new NoteEntity(); entity.setNote001("a1"); entity.setNote002("a2& ...

  7. 安装python官方的mysql库“mysql-connector-python”

    $ echo https://cdn.mysql.com/Downloads/Connector-Python/mysql-connector-python-2.1.3.tar.gz >> ...

  8. [SQL SERVER 2005]数据库差异备份及还原

    因为之前遇到还原差异备份,最开始遇到SQLServer报错:”无法还原日志备份或差异备份,因为没有文件可用于前滚“.查阅很多资料后,终于得到解决.收集整理成这篇随笔. 问题原因:出现这种错误绝大多数是 ...

  9. [转]ASP.NET页面之间传递值的几种方式

    页面传值是学习asp.net初期都会面临的一个问题,总的来说有页面传值.存储对象传值.ajax.类.model.表单等.但是一般来说,常用的较简单有QueryString,Session,Cookie ...

  10. React Native 重新建项目遇到的一些问题

    1.基本上一句话,就是本地的node太旧了,跟不上React_Native的节奏,所以需要更新node,但是单纯的更新node丫丫竟然不让我跟,因为是用Homebrew来管理的,所以先update了下 ...