一.什么是"非构造函数"的继承?
            现在有一个对象,叫"中国人".
            var Chinese = {
                nation:'中国'
            }
            还有一个对象,叫做"医生".
            var Doctor = {
                career:'医生'
            }
            请问怎么才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象?
            请注意,这两个对象都是普通对象,不是构造函数,无法使用构造函数方法来实现"继承".

二. object()方法
            json格式的发明人Douglas Crockford, 提出了一个object()函数,可以做到这一点.
            function object(o){//o是父对象
                function F(){};
                    F.prototype = o;
                    return new F();
            }
            这个object()函数,其实只做一件事,就是把子对象的prototype属性,指向父对象,从而使得子对象与父对象连在一起.
            
            使用的时候,第一步现在父对象的基础上,生成子对象:
            var Doctor = object(Chinese);
            然后,再加上 子对象本身的属性:
            Doctor.career = '医生';
            这时,子对象已经继承了父对象的属性了.
            alert(Doctor.nation);//中国

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0.3-1 object方法:非构造函数继承</title>
</head>
<body>
<script>
//普通对象,非构造函数
var Chinese = {
nation:"中国"
};
var Doctor = {
career:"医生"
};
//object()
function object(o){
function F(){};
F.prototype = o;
return new F();
} //使用
Doctor = object(Chinese);
alert(Doctor.career);//undefined
alert(Doctor.nation);//中国 Doctor.career = '医生'; alert(Doctor.career);//医生
alert(Doctor.nation);//中国
</script>
</body>
</html>

三.浅拷贝
            除了使用, "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.birthPlace = ["北京","上海","香港"];
            通过extendCopy()函数,Doctor继承了Chinese.
            var Doctor = extendCopy(Chinese);
            然后,我们为Doctor的"出生地"添加一个城市:
            Doctor.birthPlace.push("厦门");
            发生了什么事情?Chinese的"出生地"也被改掉了!
            alert(Doctor.birthPlace);//北京,上海,香港,厦门
            alert(Chinese.birthPlace);//北京,上海,香港,厦门
            所以, extendCopy()只是拷贝基本类型数据,我们把这种拷贝叫做"浅拷贝",这是早期jQuery实现继承的方式.

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0.3-2 浅拷贝:非构造函数的继承</title>
</head>
<body>
<script>
//普通对象,非构造函数
var Chinese = {
nation:'中国'
};
var Doctor = {
career:'医生'
};
//prototype链,把父对象的属性全部拷贝给子对象
function extendCopy(p){
var c = {};
for(var i in p){
c[i] = p[i];
}
c.uber = p;
return c;
}
//使用方法
Doctor = extendCopy(Chinese);
alert(Doctor.career);//undefined
alert(Doctor.nation);//中国 Doctor.career = "医生";
alert(Doctor.career);//医生
alert(Doctor.nation);//国家
</script>
</body>
</html>

四.深拷贝
            所谓"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。
            function deepcCopy(p,c){
                var c = c||{};
                for(var i in p){
                    if(typeof p[i] === 'object'){
                        c[i] = (p[i].constructor === Array)?[]:{};
                        deepcCopy(p[i],c[i]);
                    }else{
                        c[i] = p[i];
                    }
                }
                return c;
            }
            使用的时候,这样写:
            var Doctor = deepCopy(Chinese);
            现在,给父对象加一个属性,值为数组.然后,在子对象上修改这个属性:
            Chinese.birthPlace = ['北京','上海','香港'];
            Doctor.birthPlace.push("厦门");
            这时,父对象就不会受到影响了.
            alert(Doctor.birthPlace);//北京,上海,香港,厦门
            alert(Chinese.birthPlace);//北京,上海,香港
            目前,JQuery使用的就是这种继承方法.

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0.3-3深拷贝:非构造函数的继承</title>
</head>
<body>
<script>
//普通对象,非构造函数
var Chinese = {
nation:'中国',
birthPlace:["北京","上海","香港"]
};
var Doctor = {
career:'医生'
};
//深拷贝,实现数组和对象的真正拷贝,而不是引用同一个内存地址,实现方法:递归调用浅拷贝就可以了·
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;
}
//使用方法
Doctor = deepCopy(Chinese);
Chinese.birthPlace = ["北京","上海","香港"];
Doctor.birthPlace.push("厦门");
alert(Chinese.birthPlace);//北京,上海,香港
alert(Doctor.birthPlace);//北京,上海,香港,厦门
</script>
</body>
</html>

原文链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html

JS面向对象编程(三):非构造函数的继承的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

    这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例.对象之间的"继承"的五种方法.比如,现在有一个"动物"对象 ...

  7. js面向对象编程 ---- 系列教程

    原 js面向对象编程:数据的缓存 原 js面向对象编程:如何检测对象类型 原 js面向对象编程:if中可以使用那些作为判断条件呢? 原 js面向对象编程:this到底代表什么?第二篇 原 js面向对象 ...

  8. js面向对象编程(三)非构造函数的继承(转载)

    Javascript面向对象编程(三):非构造函数的继承 今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一 ...

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

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

随机推荐

  1. yii框架多文件上傳

    //控制器層 <?phpnamespace app\controllers; use app\models\Uploads;use Yii;use yii\web\Controller;use ...

  2. openstack namespace 的应用

    查看虚拟机网络连通性 1.neutron port-list | grep IP 2.neutron port-show ID 查看subnet 3.neutron subnet-show ID 查看 ...

  3. Go语言之从0到1实现一个简单的Redis连接池

    Go语言之从0到1实现一个简单的Redis连接池 前言 最近学习了一些Go语言开发相关内容,但是苦于手头没有可以练手的项目,学的时候理解不清楚,学过容易忘. 结合之前组内分享时学到的Redis相关知识 ...

  4. 强制等待&隐士等待&显示等待&元素定位方法封装

    前言 问题 学习selenium的同学估计大多数都遇见过一个问题 明明页面已经精准的定位到了元素,但是执行脚本的时候却经常报错没找到元素.其实原因很简单,就是脚本执行的速度很快,而浏览器加载页面的时候 ...

  5. CentOS 7出现Failed to start firewalld.service: Unit is masked的解决办法和firewalld 防火墙开关

    说明:刚刚使用systemctl start firewalld命令开启防火墙的时候,却开不成功,出现Failed to start firewalld.service: Unit is masked ...

  6. CDH 5.15.2 离线安装

    一.前置准备 1. 基础信息 1.1 机器 机器名 服务 hadoop1 主节点 hadoop2 data.task hadoop3 data.task 1.2 服务版本 服务 版本 cdh 5.15 ...

  7. HDU 2089:不要62(数位DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=2089 不要62 Problem Description   杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer) ...

  8. django基础知识之管理静态文件css,js,images:

    管理静态文件 项目中的CSS.图片.js都是静态文件 配置静态文件 在settings 文件中定义静态内容 STATIC_URL = '/static/' STATICFILES_DIRS = [ o ...

  9. C#中的委托和事件(下篇)

    上次以鸿门宴的例子写了一篇博文,旨在帮助C#初学者迈过委托和事件这道坎,能够用最快的速度掌握如何使用它们.如果觉得意犹未尽,或者仍然不知如何在实际应用中使用它们,那么,这篇窗体篇,将在Winform场 ...

  10. 28nm工艺下,自动生成管脚排列文件,给设计加PAD,并在PAD上面打Label的流程(含Tcl脚本)

    本文转自:自己的微信公众号<数字集成电路设计及EDA教程> 里面主要讲解数字IC前端.后端.DFT.低功耗设计以及验证等相关知识,并且讲解了其中用到的各种EDA工具的教程. 考虑到微信公众 ...