深入剖析JavaScript面向对象编程


Posted in Javascript onJuly 12, 2016

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

本节主要介绍,如何生成一个"继承"多个对象的实例。

比如,现在有一个"动物"对象的构造函数,

function Animal(){ 
this.species = "动物"; 
}

还有一个"猫"对象的构造函数,

function Cat(name,color){ 
this.name = name; 
this.color = color; 
}

怎样才能使"猫"继承"动物"呢?

1. 构造函数绑定

最简单的方法,大概就是使用call或apply方法,将父对象的构造函数绑定在子对象上,也就是在子对象构造函数中加一行:

 function Cat(name,color){ 
Animal.apply(this, arguments); 
this.name = name; 
this.color = color; 
} 
var cat1 = new Cat("大毛","黄色"); 
alert(cat1.species); // 动物

2. prototype模式

更常见的做法,则是使用prototype属性。

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

Cat.prototype = new Animal(); 
Cat.prototype.constructor = Cat; 
var cat1 = new Cat("大毛","黄色"); 
alert(cat1.species); // 动物

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

1.Cat.prototype = new Animal();

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

1.Cat.prototype.constructor = Cat;

原来,任何一个prototype对象都有一个constructor属性,指向它的构造函数。也就是说,Cat.prototype 这个对象的constructor属性,是指向Cat的。

我们在前一步已经删除了这个prototype对象原来的值,所以新的prototype对象没有constructor属性,所以我们必须手动加上去,否则后面的"继承链"会出问题。这就是第二行的意思。

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

1.o.prototype = {};

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

1.o.prototype.constructor = o;

3. 直接继承prototype

由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Cat()跳过 Animal(),直接继承Animal.prototype。

现在,我们先将Animal对象改写:

1.function Animal(){ } 
2.Animal.prototype.species = "动物";

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

Cat.prototype = Animal.prototype; 
CatCat.prototype.constructor = Cat; 
var cat1 = new Cat("大毛","黄色"); 
alert(cat1.species); // 动物

与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到 Animal.prototype。

所以,上面这一段代码其实是有问题的。请看第二行

1.Cat.prototype.constructor = Cat;

这一句实际上把Animal.prototype对象的constructor属性也改掉了!

1.alert(Animal.prototype.constructor); // Cat

4. 利用空对象作为中介

由于"直接继承prototype"存在上述的缺点,所以可以利用一个空对象作为中介。

var F = function(){}; 
F.prototype = Animal.prototype; 
Cat.prototype = new F(); 
Cat.prototype.constructor = Cat;

F是空对象,所以几乎不占内存。这时,修改Cat的prototype对象,就不会影响到Animal的prototype对象。

1.alert(Animal.prototype.constructor); // Animal

5. prototype模式的封装函数

我们将上面的方法,封装成一个函数,便于使用。

function extend(Child, Parent) { 
 
var F = function(){}; 
F.prototype = Parent.prototype; 
Child.prototype = new F(); 
Child.prototype.constructor = Child; 
Child.uber = Parent.prototype; 
}

使用的时候,方法如下

extend(Cat,Animal); 
var cat1 = new Cat("大毛","黄色"); 
alert(cat1.species); // 动物

这个extend函数,就是YUI库如何实现继承的方法。

另外,说明一点。函数体最后一行

1.Child.uber = Parent.prototype;

意思是为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。这等于是在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。

6. 拷贝继承

上面是采用prototype对象,实现继承。我们也可以换一种思路,纯粹采用"拷贝"方法实现继承。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?

首先,还是把Animal的所有不变属性,都放到它的prototype对象上。

1.function Animal(){} 
2.Animal.prototype.species = "动物";

然后,再写一个函数,实现属性拷贝的目的。

function extend2(Child, Parent) { 
var p = Parent.prototype; 
var c = Child.prototype; 
for (var i in p) { 
c[i] = p[i]; 
} 
c.uber = p; 
}

这个函数的作用,就是将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象。

使用的时候,这样写:

extend2(Cat, Animal); 
var cat1 = new Cat("大毛","黄色"); 
alert(cat1.species); // 动物

以上这篇深入剖析JavaScript面向对象编程就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JScript的条件编译
May 29 Javascript
利用了jquery的ajax实现二级联互动菜单
Dec 02 Javascript
JS获取URL中参数值(QueryString)的4种方法分享
Apr 12 Javascript
js实现九宫格图片半透明渐显特效的方法
Feb 16 Javascript
JS拖拽插件实现步骤
Aug 03 Javascript
JS常用算法实现代码
Nov 14 Javascript
JS实现基于Sketch.js模拟成群游动的蝌蚪运动动画效果【附demo源码下载】
Aug 18 Javascript
vue获取input输入值的问题解决办法
Oct 17 Javascript
JS/jQuery实现DIV延时几秒后消失或显示的方法
Feb 12 jQuery
vue-auto-focus: 控制自动聚焦行为的 vue 指令方法
Aug 25 Javascript
Js 利用正则表达式和replace函数获取string中所有被匹配到的文本(推荐)
Oct 28 Javascript
javascript设计模式 ? 迭代器模式原理与用法实例分析
Apr 17 Javascript
JS及PHP代码编写八大排序算法
Jul 12 #Javascript
微信支付 JS API支付接口详解
Jul 11 #Javascript
判断输入的字符串是否是日期格式的简单方法
Jul 11 #Javascript
JS判断日期格式是否合法的简单实例
Jul 11 #Javascript
深入浅析JavaScript中的scrollTop
Jul 11 #Javascript
js鼠标单击和双击事件冲突问题的快速解决方法
Jul 11 #Javascript
js 弹出对话框(遮罩)透明,可拖动的简单实例
Jul 11 #Javascript
You might like
PHP编实现程动态图像的创建代码
2008/09/28 PHP
php用正则表达式匹配URL的简单方法
2013/11/12 PHP
php、java、android、ios通用的3des方法(推荐)
2016/09/09 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
2016/10/08 PHP
对象的类型:本地对象(1)
2006/12/29 Javascript
JavaScript 事件查询综合
2009/07/13 Javascript
关于在IE下的一个安全BUG --可用于跟踪用户的系统鼠标位置
2013/04/17 Javascript
JQuery获取样式中的background-color颜色值的问题
2013/08/20 Javascript
一个JS函数搞定网页标题(title)闪动效果
2014/05/13 Javascript
js事件绑定快捷键以ctrl+k为例
2014/09/30 Javascript
JS中JSON对象和String之间的互转及处理技巧
2016/04/06 Javascript
JavaScript的Backbone.js框架环境搭建及Hellow world示例
2016/05/07 Javascript
Javascript基础_标记文字的实现方法
2016/06/14 Javascript
JavaScript  event对象整理及详细介绍
2016/10/10 Javascript
JS常用函数和常用技巧小结
2016/10/15 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
2016/12/24 Javascript
React Native中TabBarIOS的简单使用方法示例
2017/10/13 Javascript
学习node.js 断言的使用详解
2019/03/18 Javascript
安装好Pycharm后如何配置Python解释器简易教程
2019/06/28 Python
python算法题 链表反转详解
2019/07/02 Python
Django基础三之视图函数的使用方法
2019/07/18 Python
django 中QuerySet特性功能详解
2019/07/25 Python
TensorFlow车牌识别完整版代码(含车牌数据集)
2019/08/05 Python
浅析PEP572: 海象运算符
2019/10/15 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
Python Tornado核心及相关原理详解
2020/06/24 Python
俄罗斯茶和咖啡网上商店:Tea.ru
2021/01/26 全球购物
如何实现jdbc性能优化
2012/07/30 面试题
英文版银行求职信
2013/10/09 职场文书
后勤人员岗位职责
2013/12/17 职场文书
党员政治学习材料
2014/05/14 职场文书
城管执法人员纪律作风整顿思想汇报
2014/09/13 职场文书
小学教师岗位职责
2015/04/02 职场文书
公司趣味运动会开幕词
2016/03/04 职场文书
Python基础之数据类型知识汇总
2021/05/18 Python
python缺失值填充方法示例代码
2022/12/24 Python