这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承"。

今天是最后一个部分,介绍不使用构造函数实现"继承"。

一、什么是"非构造函数"的继承?

比如,现在有一个对象,叫做"中国人"。

  var Chinese = {
    nation:'中国'
  };

还有一个对象,叫做"医生"。

  var Doctor ={
    career:'医生'
  }

请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象?

这里要注意,这两个对象都是普通对象,不是构造函数,无法使用构造函数方法实现"继承"。

二、object()方法

json格式的发明人Douglas Crockford,提出了一个object()函数,可以做到这一点。

  function object(o) {

    function F() {}

    F.prototype = o;

    return new F();

  }

这个object()函数,其实只做一件事,就是把子对象的prototype属性,指向父对象,从而使得子对象与父对象连在一起。

使用的时候,第一步先在父对象的基础上,生成子对象:

  var Doctor = object(Chinese);

然后,再加上子对象本身的属性:

  Doctor.career = '医生';

这时,子对象已经继承了父对象的属性了。

  alert(Doctor.nation); //中国

三、浅拷贝

除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。

下面这个函数,就是在做拷贝:

  function extendCopy(p) {

    var c = {};

    for (var i in p) { 
      c[i] = p[i];
    }

    c.uber = p;

    return c;
  }

使用的时候,这样写:

  var Doctor = extendCopy(Chinese);

  Doctor.career = '医生';

  alert(Doctor.nation); // 中国

但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。

请看,现在给Chinese添加一个"出生地"属性,它的值是一个数组。

  Chinese.birthPlaces = ['北京','上海','香港'];

通过extendCopy()函数,Doctor继承了Chinese。

  var Doctor = extendCopy(Chinese);

然后,我们为Doctor的"出生地"添加一个城市:

  Doctor.birthPlaces.push('厦门');

发生了什么事?Chinese的"出生地"也被改掉了!

  alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门

  alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门

所以,extendCopy()只是拷贝基本类型的数据,我们把这种拷贝叫做"浅拷贝"。这是早期jQuery实现继承的方式。

四、深拷贝

所谓"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。

  function deepCopy(p, c) {

    var c = c || {};

    for (var i in p) {

      if (typeof p[i] === 'object') {

        c[i] = (p[i].constructor === Array) ? [] : {};

        deepCopy(p[i], c[i]);

      } else {

         c[i] = p[i];

      }
    }

    return c;
  }

使用的时候这样写:

  var Doctor = deepCopy(Chinese);

现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性:

  Chinese.birthPlaces = ['北京','上海','香港'];

  Doctor.birthPlaces.push('厦门');

这时,父对象就不会受到影响了。

  alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门

  alert(Chinese.birthPlaces); //北京, 上海, 香港

目前,jQuery库使用的就是这种继承方法。

javascript之非构造函数的继承的更多相关文章

  1. (三)Javascript面向对象编程:非构造函数的继承

    Javascript面向对象编程:非构造函数的继承   这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使 ...

  2. Javascript面向对象编程(三):非构造函数的继承(对象的深拷贝与浅拷贝)

    Javascript面向对象编程(三):非构造函数的继承   作者: 阮一峰 日期: 2010年5月24日 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现&quo ...

  3. javascript面向对象(三):非构造函数的继承

    本文来自阮一峰 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使用构造函数实现"继承" ...

  4. Javascript面向对象编程(三) --- 非构造函数的继承

    一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做&qu ...

  5. 转载:javascript面向对象编程:非构造函数的继承

    一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做&qu ...

  6. Javascript面向对象编程(三):非构造函数的继承 by 阮一峰

    今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Ch ...

  7. (转)Javascript面向对象编程(三):非构造函数的继承(作者:阮一峰)

    不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { na ...

  8. Javascript面向对象编程(三):非构造函数的继承

    转载自:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html 一.什 ...

  9. Javascript面向对象编程:非构造函数的继承

    今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Ch ...

随机推荐

  1. Understanding Convolutional Neural Networks for NLP

    When we hear about Convolutional Neural Network (CNNs), we typically think of Computer Vision. CNNs ...

  2. Java基础语法(基本语句)

    Java基础语法 标识符在程序中自定义的一些名称.由26个英文字母大小写,数字:0-9符号:_&组成定义合法标识符规则:1.      数字不可以开头2.      不可以使用关键字Java中 ...

  3. Linux命令: ls -l显示文件和目录的详细资料

    ls -l 显示文件和目录的详细资料

  4. Linux服务器配置---配置telnet

    配置telnet      通过配置文件,我们可以设置telnet的连接时间.连接数.连接ip等,实现更加安全的连接 1.设置连接时间,参数“access_times” [root@localhost ...

  5. 面向对象之(非)绑定方法,反射,isinstance与issubclass

    isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查obj是否是类 cls 的对象 class Foo(object): pa ...

  6. 嵌入式C语言--面试题

    C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法.这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是 ...

  7. Git 基础 —— 常用命令

    Git 基础学习系列 Git 基础 -- 安装 配置 别名 对象 Git 基础 -- 常用命令 Git 基础 -- 常见使用场景 Git基础 -- Github 的使用 git init 创建 Git ...

  8. win7下把电脑设置成wlan热

    有很多公司没有无线网,只有自己的电脑可以上网,现在设置热点,可以手机上网 步骤: 1.看自己的网卡是否支持承载网络,如果不支持,本法就不适用 在CMD里用    netsh wlan show dri ...

  9. 解决Eclipse 项目报错:Unbound classpath container: ‘JRE System Library [JavaSE-1.7]

    MyEclipse出现下面两条报错: The project cannot be built until build path errors are resolved HelloWord Unknow ...

  10. 配置文件(Machine.config、Web.config、App.config)

    Machine.config1.该文件在Windows目录下\Microsoft.net\framework\[version]\Config\2.为了提高性能,该文件只包含不同于默认值的设置.并且定 ...