一、你必须知道的

1> 原型及原型链在继承中起到了关键的作用。所以你一定要理解他们。2> 不会JS中的OOP,你也太菜了吧!(第一篇)

二、继承的6种方法

1> 原型链继承

原型链继承是通过创建Super的实例,并将该实例赋值给Sub.prototype来实现的。

实现的本质是:重写子类型的原型对象,代之以超类型的实例。

  1. function Super(){
  2. this.name = 'JChen___';
  3. }
  4. Super.prototype.getSuperName = function(){
  5. return this.name;
  6. }
  7.  
  8. function Sub(){
  9. this.subname = 'JChen___son';
  10. }
  11. Sub.prototype = new Super(); //原型继承体现在这里
  12. Sub.prototype.getSubName = function(){
  13. return this.subname;
  14. }
  15.  
  16. var instance = new Sub();

注意:此时instance.constructor现在指向的是Super的,这是因为Sub.prototype指向了Super.prototype,而Super.prototype.constructor = Super。

原型链的问题:类似于利用原型创建对象,原型共享的特性也是原型链继承的最大问题。

2> 借用构造函数继承

在解决原型中包含引用类型值所带来的问题的过程中,我们开始使用一种叫做借用构造函数的技术。

这种技术的基本思想相当简单:在子类型构造函数的内部调用超类型构造函数

这样一来,就会在新子类对象上执行超类函数中定义的所有对象初始化代码。结果,每个子类的实力都会有自己的超类中属性的副本了。

  1. function Super2(name){
  2. this.colors = ['red', 'blue'];
  3. this.name = name;
  4. }
  5.  
  6. function Sub2(){
  7. Super2.call(this, 'JChen___2'); //借用构造函数技术体现在这里
  8. this.age = 29;
  9. }
  10.  
  11. var instance1 = new Sub2();
  12. instance1.colors.push('black');
  13. var instance2 = new Sub2();
  14. instance2.colors.push('green');

借助构造函数继承的问题:

1): 方法都在构造函数中定义,无法复用。

2): 在超类型的原型中的方法对子类是不可见的。

3> 组合继承(原型+借用构造)

组合继承指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。

组合继承的思路:使用原型链实现对方法和属性的继承,通过借用构造函数实现对实例属性的继承。

  1. function Super3(name){
  2. this.name = name;
  3. this.colors = ['red', 'blue'];
  4. }
  5. Super3.prototype.sayName = function(){
  6. return this.name;
  7. }
  8.  
  9. function Sub3(name, age) {
  10. Super3.call(this, name);
  11. this.age = age;
  12. }
  13. Sub3.prototype = new Super3(); //解决借用构造函数技术的缺点
  14. Sub3.prototype.constructor = Sub3; //纠正原型继承改变了的构造函数
  15. Sub3.prototype.sayAge = function(){
  16. return this.age;
  17. }

组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为JavaScript中最常用的继承模式。

组合继承的问题:两次调用超类构造函数。

4> 原型式继承

原型式继承的思路:借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

  1. function object(o){ //原型式继承的关键
  2. function F(){}
  3. F.prototype = o;
  4. return new F();
  5. }
  6. var person = {
  7. name: 'JChen___4',
  8. colors: ['blue']
  9. }
  10. var person1 = object(person);
  11. person1.name = 'JChen___4___2'
  12. person1.colors.push('red');
  13. var person2 = object(person);
  14. person2.name = 'JChen___4___3';
  15. person2.colors.push('green');

原型式继承的问题:同原型链一样,他也有共享的劣势。

5> 寄生式继承

寄生式继承的思路:创建一个仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后再返回该对象

  1. function createAnother(origin){ //寄生式继承的关键
  2. var clone = object(origin);
  3. clone.sayHi = function(){
  4. return 'Hi';
  5. };
  6. return clone;
  7. }
  8. var person = {
  9. name: 'JChen___4',
  10. colors: ['blue']
  11. }
  12. var person1 = createAnother(person);

寄生式继承的问题:像构造函数一样,由于不能做到函数的复用而降低效率。

6> 寄生组合式继承

寄生组合式继承:通过借用构造函数来借用属性,通过原型链的混成形式来继承方法。

其背后的思想是:不必为了指定子类型的原型而调用超类型的构造函数,我们需要的无非就是超类型的一个副本而已。

  1. function object(o){
  2. function F(){}
  3. F.prototype = o;
  4. return new F();
  5. }
  6. function inheritProto(subType, superType){ //避免第一调用构造函数的关键
  7. var proto = object(superType.prototype);
  8. proto.constructor = subType;
  9. subType.prototype = proto;
  10. }
  11.  
  12. function Super6(name){
  13. this.name = name;
  14. this.colors = ['red', 'blue'];
  15. }
  16. Super6.prototype.sayName = function(){
  17. return this.name;
  18. }
  19.  
  20. function Sub6(name, age){
  21. Super6.call(this, name);
  22. this.age = age;
  23. }
  24.  
  25. inheritProto(Sub6, Super6);
  26.  
  27. Sub6.prototype.sayAge = function(){
  28. return this.age;
  29. }
  30.  
  31. var instance1 = new Sub6('JChen___6', '12');
  32. instance1.colors.push('black');

开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。

三、总结

这就是JavaScript中的6种继承方式,如果大家能够画出每个继承的原型链关系图,那么继承就是小菜一碟了。

不会JS中的OOP,你也太菜了吧!(第二篇)的更多相关文章

  1. 小结JS中的OOP(下)

    关于JS中OOP的具体实现,许多大神级的JS专家都给出了自己的方案. 一:Douglas Crockford 1.1 Douglas Crockford实现的类继承 /** * 原文地址:http:/ ...

  2. 小结JS中的OOP(中)

    此篇文章主要是提炼<JavaScript高级程序设计>中第六章的一些内容. 一:JS中OOP相关的概念 开始之前先总结JS中OOP相关的一些概念: 构造函数:JS中的构造函数就是普通的函数 ...

  3. 小结JS中的OOP(上)

    前言:大家都知道,OOP有三大特性:封装,继承,多态.下面是自己对这三个特性的理解: 封装:把属性与方法整合到某种数据类型中.目的是让类的使用者按类的编写者的意愿去使用类.在封装过程中会一般会做两件事 ...

  4. js面向对象编程:this究竟代表什么?第二篇

         总觉得自己弄明确了js中this的含义.this总是指向调用方法的对象,作为方法调用,那么this就是指实例化的对象.但前几天自己写脚本却遇到了一个非常奇怪的问题.    代码例如以下:   ...

  5. 不会JS中的OOP,你也太菜了吧!(第一篇)

    一.你必须知道的 1) 字面量 2) 原型 3) 原型链 4) 构造函数 5) 稳妥对象(没有公共属性,而且其方法也不引用this的对象.稳妥对象适合用在安全的环境中和防止数据被其它程序改变的时候) ...

  6. JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解

      前  言 JRedu 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于 ...

  7. Cookie和Session在Node.JS中的实践(一)

    Cookie和Session在Node.JS中的实践(一) Cookie和Session是一个非常有趣的概念,也是一个老生常谈的话题.然而,作者看了许多文章,也翻看了几本书籍,它们对Cookie和Se ...

  8. 进阶学习js中的执行上下文

    在js中的执行上下文,菜鸟入门基础 这篇文章中我们简单的讲解了js中的上下文,今天我们就更进一步的讲解js中的执行上下文. 1.当遇到变量名和函数名相同的问题. var a = 10; functio ...

  9. JS中三目运算符和if else的区别分析与示例

    本文是通过示例详细分析了JS中三目运算符和if else的区别,是篇非常不错的文章,这里推荐给大家.   今天写了一个图片轮播的小demo,用到了判断 先试了一下if else,代码如下: 复制代码代 ...

随机推荐

  1. Jquery设置select控件指定text的值为选中项

    <select name="streetid" id="streetid"> <option value="4">北 ...

  2. sql取字段特定符号的前/后

    declare @canshu varchar(200)set @canshu='24§咨询客户'--某符号之后的字段内容select substring(@canshu,charindex('§', ...

  3. c/c++基本问题

    1. 使用g++将文件编译成库文件 g++ -c -O2 -fPIC test.cpp -o test.o && g++ -shared -Wall -o test.so test.o ...

  4. DPDK内存管理-----(一)初始化

    1 前言 DPDK通过使用hugetlbfs,减少CPU TLB表的Miss次数,提高性能. 2 初始化 DPDK的内存初始化工作,主要是将hugetlbfs的配置的大内存页,根据其映射的物理地址是否 ...

  5. JQuery 的几个有用的技巧

    JQuery代码 /* 新窗口打开链接:JQuery filter attr * 禁止鼠标弹出右键菜单:DOM contextmenu * 回到页面顶端:DOM scrollTo * 动态更换Css样 ...

  6. Spring Richclient — 企业级富客户端开发框架介绍,第 1 部分

    Spring Richclient — 企业级富客户端开发框架介绍,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-spring-richc ...

  7. 【转】准确理解CSS clear:left/right的含义及实际用途

    零.说点什么 好久没更新了.并不是在折腾什么大作,而是广度学习与实践中,加上婚礼等诸多大事,所以产出较少. 今天这篇也只是小作,博客是自己很好的学习工具,只要我学习不止,博客也会不断更新的. 我们平时 ...

  8. Yii整合ZF2及soap实例

    一)如何整合? // change the following paths if necessary $yii = dirname(__FILE__).'/framework/yii.php'; $c ...

  9. PHP函数:生成N个不重复的随机数

    思路:将生成的随机数存入数组,再在数组中去除重复的值,即可生成一定数量的不重复随机数. 程序: <?php /* * array unique_rand( int $min, int $max, ...

  10. 【转】MySQL GRANT REVOKE用法

    MySQL的权限系统围绕着两个概念: 认证->确定用户是否允许连接数据库服务器 授权->确定用户是否拥有足够的权限执行查询请求等. 如果认证不成功的话,哪么授权肯定是无法进行的. revo ...