本文抄袭仅供学习
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html

一、 构造函数绑定

  第一种方法也是最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上

二、 prototype模式  

原来,任何一个prototype对象都有一个constructor属性,指向它的构造函数。

更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性

如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。

  Cat.prototype = new Animal();

  Cat.prototype.constructor = Cat;

  var cat1 = new Cat("大毛","黄色");

  alert(cat1.species); // 动物

代码的第一行,我们将Cat的prototype对象指向一个Animal的实例。

  Cat.prototype = new Animal();

它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。但是,第二行又是什么意思呢?

  Cat.prototype.constructor = Cat;

原来,任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有"Cat.prototype = new Animal();"这一行,Cat.prototype.constructor是指向Cat的;加了这一行以后,Cat.prototype.constructor指向Animal。

  alert(Cat.prototype.constructor == Animal); //true

更重要的是,每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。

  alert(cat1.constructor == Cat.prototype.constructor); // true

因此,在运行"Cat.prototype = new Animal();"这一行之后,cat1.constructor也指向Animal!

  alert(cat1.constructor == Animal); // true

这显然会导致继承链的紊乱(cat1明明是用构造函数Cat生成的),因此我们必须手动纠正,将Cat.prototype对象的constructor值改为Cat。这就是第二行的意思。

这是很重要的一点,编程时务必要遵守。下文都遵循这一点,即如果替换了prototype对象,

  o.prototype = {};

那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。

  o.prototype.cons

三、 直接继承prototype

缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype。

第三种方法是对第二种方法的改进。由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Cat()跳过 Animal(),直接继承Animal.prototype。

将Cat的prototype对象,然后指向Animal的prototype对象,这样就完成了继承。

  Cat.prototype = Animal.prototype;

  Cat.prototype.constructor = Cat;

四、 利用空对象作为中介

由于"直接继承prototype"存在上述的缺点,所以就有第四种方法,利用一个空对象作为中介。

  var F = function(){};

  F.prototype = Animal.prototype;

  Cat.prototype = new F();

  Cat.prototype.constructor = Cat;

封装成一个函数,便于使用。

  function extend(Child, Parent) {

    var F = function(){};

    F.prototype = Parent.prototype;

    Child.prototype = new F();

    Child.prototype.constructor = Child;

    Child.uber = Parent.prototype;

  }

五、 拷贝继承

把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?这样我们就有了第五种方法。

实现属性拷贝的目的。

  function extend2(Child, Parent) {

    var p = Parent.prototype;

    var c = Child.prototype;

    for (var i in p) {

      c[i] = p[i];

      }

    c.uber = p;

  }

JavaScript五种继承方式详解的更多相关文章

  1. C++的三种继承方式详解以及区别

    目录 目录 C++的三种继承方式详解以及区别 前言 一.public继承 二.protected继承 三.private继承 四.三者区别 五.总结 后话 C++的三种继承方式详解以及区别 前言 我发 ...

  2. Spring事务Transaction配置的五种注入方式详解

    Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...

  3. js的2种继承方式详解

    js中继承可以分为两种:对象冒充和原型链方式 一.对象冒充包括三种:临时属性方式.call()及apply()方式1.临时属性方式 复制代码代码如下: function Person(name){   ...

  4. 《网页设计基础——CSS的四种引入方式详解》

    网页设计基础--CSS的四种引入方式详解     一.行内式:   规则: 1. 行内式是所有样式方法中最为直接的一种,它直接对HTML的标记使用style属性,然后将CSS代码直接写在其中.   格 ...

  5. python selenium 三种等待方式详解[转]

    python selenium 三种等待方式详解   引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...

  6. JavaScript继承方式详解

    原文链接 : http://segmentfault.com/a/1190000002440502 js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继 ...

  7. JavaScript继承方式详解[转]

    js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念.所以,要想实现 ...

  8. JavaScript 继承方式详解

    js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承)类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念.所以,要想实现继 ...

  9. 【设计模式+原型理解】第三章:javascript五种继承父类方式

    [前言] 我们都知道,面向对象(类)的三大特征:封装.继承.多态 继承:子类继承父类的私有属性和公有方法 封装:把相同的代码写在一个函数中 多态: ->重载:JS严格意义上是没有重载,但可以通过 ...

随机推荐

  1. 通过xshell在linux上安装JDK8

    通过xshell在linux上安装JDK8 0)新建连接,输入名称与主机IP地址 1)输入用户名与密码,创建连接 2)执行命令cd /usr/进入文件夹:再输入mkdir java创建java文件夹 ...

  2. 阿里云SSL证书到期(续期)图文教程

    今天公司项目突然报错 后来查询是SSL证书过期了.友情提示: 证书产品仅支持新签发.不支持续费.证书到期前需在阿里云SSL证书控制台重新购买和申请证书. 登录阿里云控制台,点击产品与服务,在搜索框搜索 ...

  3. SQL中EXCEPT函数在 Mysql 和 sqlServer 中的替代方法

    示例摘自:极客代码:http://wiki.jikexueyuan.com/project/sql/useful-functions/except-clause.html EXCEPT 子句 EXCE ...

  4. input输入框类型

    输入大小写字母.数字.下划线: <input type="text" onkeyup="this.value=this.value.replace(/[^\w_]/ ...

  5. Thinkphp5所有页面验证用户是否登陆

    新建Base.php控制器,所有的页面继承自它 <?php namespace app\index\controller; use think\Controller; class Base ex ...

  6. rhel6.4扩充swap分区

    状况:Red hat 6.4 swap分区不足 解决:扩充swap ================================================================== ...

  7. go学习笔记-常见命令

    常见命令 go 命令 可以在控制台执行go来查看 go Go is a tool for managing Go source code. Usage: go <command> [arg ...

  8. (数据科学学习手札05)Python与R数据读入存出方式的总结与比较

    在数据分析的过程中,外部数据的导入和数据的导出是非常关键的部分,而Python和R在这方面大同小异,且针对不同的包或模块,对应着不同的函数来完成这部分功能: Python 1.TXT文件 导入: 以某 ...

  9. 理解Canvas像素边界

    大家看下面的例子 var context = document.getElementById('canvas').getContext('2d'); context.lineWidth = 1; co ...

  10. android去掉button默认的点击阴影

    查了资料,发现别人都是说加一个style属性. style="?android:attr/borderlessButtonStyle" 加上了确实管用,但是我绝不是不求甚解的人.追 ...