JavaScript中继承的实现方法--详解
最近看《JavaScript王者归来》中关于实现继承的方法,做了一些小总结:
JavaScript中要实现继承,其实就是实现三层含义:
1、子类的实例可以共享父类的方法;
2、子类可以覆盖父类的方法或者扩展新的方法;
3、子类和父类都是子类实例的“类型”。
JavaScript中,并不直接从语法上支持继承,但是可以通过模拟的方法来实现继承,以下是关于实现继承的几种方法的总结:
1、构造继承法
2、原型继承法
3、实例继承法
4、拷贝继承法
1、构造继承法:
在子类中执行父类的构造函数。
<SCRIPT LANGUAGE="JavaScript">2
<!--3
function dwn(s)4

{5
document.write(s+'<br/>');6
}7

8
//定义一个Collection类型9
function Collection(size)10

{11

this.size = function()
{return size}; //公有方法,可以被继承12
}13

14
//定义一个_Collection类型15
function _Collection(_size)16

{17

this._size = function()
{return _size}; //公有方法,可以被继承18
}19

20
Collection.prototype.isEmpty = function() //静态方法,不能被继承21

{22
return this.size() == 0;23
}24

25
//定义一个ArrayList类型,它“继承”Colleciton类型26
function ArrayList()27

{28
var m_elements = []; //私有成员,不能被继承29
m_elements = Array.apply(m_elements,arguments);30

31
//ArrayList类型继承Colleciton32
this.base = Collection;33
this.base.call(this,m_elements.length);34

35
this.base = _Collection; //可以实现多态继承36
this.base.call(this,m_elements.length); 37

38
this.add = function()39

{40
return m_elements.push.apply(m_elements,arguments); 41
}42

43
this.toArray = function()44

{45
return m_elements;46
}47
}48

49
ArrayList.prototype.toString = function()50

{51
return this.toArray().toString();52
}53

54
//定义一个SortedList类型,它继承ArrayList类型55
function SortedList()56

{57
//SortedList类型继承ArrayList58
this.base = ArrayList;59
this.base.apply(this,arguments);60

61
this.sort = function()62

{63
var arr = this.toArray();64
arr.sort.apply(arr,arguments);65
}66
}67

68
//构造一个ArrayList69
var a = new ArrayList(1,2,3);70
dwn(a); //1,2,371
dwn(a.size()); //3 a从Collection继承了size()方法72
dwn(a.isEmpty); //undefined 但是a没有继承到isEmpty()方法73

74
dwn(a._size()); //3 可以实现多态继承75

76
//构造一个SortedList77
var b = new SortedList(3,1,2);78
dwn(b.toArray());79
b.add(4,0); //b 从ArrayList继承了add()方法80
dwn(b.toArray()); //b从ArrayList继承了toArray()方法81
b.sort(); //b自己实现sort()方法82
dwn(b.toArray());83
dwn(b);84
dwn(b.size()); //b从Collection继承了size()方法85
//-->86
</SCRIPT>2、原型继承法:
JavaScript是一种基于原型的语言。
要了解什么是“原型继承法”,先了解一下prototype的特性:prototype的最大特性是能够让对象实例共享原型对象的属性,因此如果把某个对象作为一个类型的原型,那么我们说这个类型的所有实例都一这个对象为原型。这个时候,实际上这个对象的类型也可以作为那些以这个对象为原型的实例的类型。
假如:Point类的对象作为Point2D类型的原型(Point2D.prototype = new Point(2)),那么说Point2D的所有实例都是以Point类的对象为原型。此时,实际上Point类就可以作为Point2D类型的对象的类型(相当于Point2D类型“继承”了Point类型)。
见例:
<SCRIPT LANGUAGE="JavaScript">2
<!--3
function dwn(s)4

{5
document.write(s+"<br/>");6
}7

8
function Point(dimension) //定义一个Point类9

{10
this.dimension = dimension;11
}12

13
Point.prototype.distance = function() //静态方法,可以被继承14

{15
return this.dimension*2;16
}17

18
function Point2D(x,y) //定义一个Point2D类19

{20
this.x = x;21
this.y = y;22
}23

24
Point2D.prototype = new Point(2); //运行“原型继承法”使Point2D继承Point25

26
function Point3D(x,y,z) //定义Point3D类27

{28
this.x = x;29
this.y = y;30
this.z = z;31
}32

33
Point3D.prototype = new Point(3); //Point3D继承Point类34

35
var p2 = new Point2D(1,2); //构造一个Point2D对象36

37
var p3 = new Point3D(1,2,3); //构造一个Point3D对象38

39
dwn(p2.dimension); //240
dwn(p3.dimension); //341
dwn(p2.distance()); //4 可以继承静态方法42
dwn(p3.distance()); //6 可以继承静态方法43

44
dwn(p2 instanceof Point2D); //p2是Point2D对象45
dwn(p2 instanceof Point); //Point2D继承Point,p2是Point对象46

47
dwn(p3 instanceof Point3D); //p3是Point3D对象48
dwn(p3 instanceof Point); //Point3D继承Point,p3是Point对象49

50
//-->51
</SCRIPT>3、实例继承法
构造继承法和原型继承法各有各的缺点,如:
构造继承法没有办法继承类型的静态方法,因此它无法很好的继承JavaScript的核心对象。
原型继承法虽然可以继承静态方法,但是依然无法很好地继承核心对象中的不可枚举方法。
其中,javascript核心对象包括:
Array 表述数组。
Boolean 表述布尔值。
Date 表述日期。
Function 指定了一个可编译为函数的字符串 JavaScript 代码。
Math 提供了基本的数学常量和函数;如其 PI 属性包含了π的值。
Number 表述实数数值。
Object 包含了由所有 JavaScript 对象共享的基本功能。
RegExp 表述了一个正则表达式;同时包含了由所有正则表达式对象的共享的静态属性。
String 表述了一个 JavaScript 字符串。
(1)构造继承法的局限性:
<SCRIPT LANGUAGE="JavaScript">2
<!--3
function MyDate()4

{5
this.base = Date;6
this.base.apply(this,arguments);7
}8

9
var date = new MyDate();10
alert(date.toGMTSring()); //对象不支持此方法或属性11
//核心对象(Date)的某些方法不能被构造继承,原因是核心对象并不像我们自定义的一般对象那样在构造函数里进行赋值或初始化操作。12
//--> (2)原型继承的局限性
<SCRIPT LANGUAGE="JavaScript">2
<!--3
function MyDate()4

{5

6
}7
MyDate.prototype = new Date();8
var date = new MyDate();9
alert(date.toGMTSring()); //'[object]不是日期对象'10
//-->11
</SCRIPT>以上说明了“构造继承法”和“原型继承法”的局限性(局限之一:不能很好的继承核心对象),下面介绍如何用实例继承法来继承核心对象。
在介绍之前首先了解以下关于构造函数:
构造函数通常没有返回值,它们只是初始化由this值传递进来的对象,并且什么也不返回。如果函数有返回值,被返回的对象就成了new表达式的值。
<SCRIPT LANGUAGE="JavaScript">2
<!--3
function dwn(s)4

{5
document.write(s+'<br/>');6
}7
function MyDate()8

{9
var instance = new Date(); //instance是一个新创建的日期对象10
instance.printDate = function() //对日期对象instance扩展printDate()方法11

{12
dwn(instance.toLocaleString());13
}14
return instance; //将instance作为构造函数的返回值返回15
}16

17
var date = new MyDate();18
dwn(date.toGMTString());19
date.printDate(); 20
dwn(date instanceof MyDate); //false21
dwn(date instanceof Date); //true22
//对象的构造函数将会是实际构造的对象的构造函数(new Date()),而不是类型本身的构造函数(new MyDate())23
//-->24
</SCRIPT> 4、拷贝继承法
拷贝继承法是通过对象属性的拷贝来实现继承。
<script language="JavaScript">2
function Point(dimension)3

{4
this.dimension = dimension;5
}6

7
var Point2D = function(x,y)8

{9
this.x = x;10
this.y = y;11
}12

13
Point2D.extend = function()14

{15
var p = new Point(2);16
for(var each in p) //将对象的属性进行一对一的复制。17

{18
//this[each] = p[each];19
this.prototype[each] = p[each];20
}21
}22
Point2D.extend();23
//alert(Point2D.dimension);24
alert(Point2D.prototype.dimension);25
</script>5、几种继承方式的比较
|
比较项 |
构造继承 |
原型继承 |
实例继承 |
拷贝继承 |
|
静态属性继承 |
N |
Y |
Y |
Y |
|
内置(核心)对象继承 |
N |
部分 |
Y |
Y |
|
多参多重继承 |
Y |
N |
Y |
N |
|
执行效率 |
高 |
高 |
高 |
低 |
|
多继承 |
Y |
N |
N |
Y |
|
instanceof |
false |
true |
false |
false |
JavaScript中继承的实现方法--详解的更多相关文章
- javascript中set与get方法详解
其中get与set的使用方法: 1.get与set是方法,因为是方法,所以可以进行判断. 2.get是得到 一般是要返回的 set 是设置 不用返回 3.如果调用对象内部的属性约定的命名方式是_a ...
- Javascript中数组重排序方法详解
在数组中有两个可以用来直接排序的方法,分别是reverse()和sort().下面通过本文给大家详细介绍,对js 数组重排序相关知识感兴趣的朋友一起看看吧. 1.数组中已存在两个可直接用来重排序的方法 ...
- php_DWZ-JUI中碰到的问题解决方法详解(thinkphp+dwz)
原文:php_DWZ-JUI中碰到的问题解决方法详解(thinkphp+dwz) 折腾了两天,dwz删除后,数据不能自动刷新,解决方案,直接看图 . 1. 删除.修改状态后无法刷新记录: 在dwz. ...
- python中requests库使用方法详解
目录 python中requests库使用方法详解 官方文档 什么是Requests 安装Requests库 基本的GET请求 带参数的GET请求 解析json 添加headers 基本POST请求 ...
- JavaScript中的鼠标滚轮事件详解
JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...
- PHP 中 16 个魔术方法详解
PHP 中 16 个魔术方法详解 前言 PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __constru ...
- 并发编程(六)Object类中线程相关的方法详解
一.notify() 作用:唤醒一个正在等待该线程的锁的线程 PS : 唤醒的线程不会立即执行,它会与其他线程一起,争夺资源 /** * Object类的notify()和notifyAll()方法详 ...
- JavaScript中typeof和instanceof深入详解
这次主要说说javascript的类型判断函数typeof和判断构造函数原型instanceof的用法和注意的地方. typeof 先来说说typeof吧.首先需要注意的是,typeof方法返回一个字 ...
- JavaScript 中 apply 、call 的详解
apply 和 call 的区别 ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已. 原文作者:林 ...
随机推荐
- 设计模式 - 动态代理原理及模仿JDK Proxy 写一个属于自己的动态代理
本篇文章代码内容较多,讲的可能会有些粗糙,大家可以选择性阅读. 本篇文章的目的是简单的分析动态代理的原理及模仿JDK Proxy手写一个动态代理以及对几种代理做一个总结. 对于代理模式的介绍和讲解,网 ...
- HTML5 + WebGL 实现的垃圾分类系统
前言 垃圾分类,一般是指按一定规定或标准将垃圾分类储存.分类投放和分类搬运,从而转变成公共资源的一系列活动的总称.分类的目的是提高垃圾的资源价值和经济价值,力争物尽其用.垃圾在分类储存阶段属于公众的私 ...
- Python开发专属壁纸下载与轮换程序
本人对于壁纸一直偏佛系,不爱特意去找一堆壁纸.因此用Python简单地搞了一个自动下载壁纸,定时随机轮换的功能来自娱自乐,顺便分享给大家. 原文链接:https://www.codernice.top ...
- salt-api 配置使用
salt-api 安装 配置源 (系统环境s示例是centos6) epel 源 rpm -Uvh https://mirrors.tuna.tsinghua.edu.cn/epel/6/i386/ ...
- ES6 —— entries(),keys()和values()
ES6 提供三个新的方法 —— entries(),keys()和values() —— 用于遍历数组.它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的 ...
- 聊聊 Vue 中 axios 的封装
聊聊 Vue 中 axios 的封装 axios 是 Vue 官方推荐的一个 HTTP 库,用 axios 官方简介来介绍它,就是: Axios 是一个基于 promise 的 HTTP 库,可以用在 ...
- SQL server数据库系统部分常用的存储过程及说明
--SQL server数据库系统常用的存储过程 exec sp_databases --能看到所有具有权限的数据库名,大小和备注 exec sp_helpdb --数据库名,大小,管理员,创建时间状 ...
- Linux防火墙常用操作
/tcp —— 配置白名单 sudo systemctl start firewalld — 启动防火墙 sudo firewall-cmd --state - 看状态 sudo firewall-c ...
- Ubunut18 安装docker环境&&AWD攻防平台部署
docker:有两个版本:docker-ce(社区版)和docker-ee(企业版). 参考官网地址:https://docs.docker.com/engine/installation/linux ...
- [NOIp2010] luogu P1541 乌龟棋
英语老师讲 mind map,真想说一句"声微饭否".为什么wyy的歌词总是快一点点.在报csp. 题目描述 你在一个序列上向正方向行走,起点是 a[0]a[0]a[0].每一步可 ...