JavaScript的继承实现小结


Posted in Javascript onMay 07, 2017

最近在忙前端的工作,因为之前做.net和php的开发比较多,前端开发喜欢把库拿来就用,几次事实证明,不懂原理,连改代码也改不好,所以还是下定决心研究下JavaScript的几个技术难点。

0x1.JavaScript的对象和构造函数

定义一个JavaScript对象可以这么定义

var a = {
	x : 1,
	y : 2,
	add : function () {
		return this.x + this.y;
	},
	mul : function () {
		return this.x * this.y;
	}
}

这样,你就定义了一个变量a,这个变量除了有x和y两个公有成员外,还有两个add和mul两个函数(公有方法)。但是这样的定义方法的缺点有2条:

1.批量生成对象很不方便,如果你var b=a;那么你每次修改b的成员,都会同时改掉a的成员,因为JavaScript的引用机制

2.如果每次生成对象需要自定义一些成员,都要写出相应的赋值操作,增加代码行数。

所以,在定义一个JavaScript对象之前,我们可以先定义一个构造函数。

function A(x, y) {
	this.x = x;
	this.y = y;
	this.add = function () {
		return this.x + this.y;
	}
	this.mul = function () {
		return this.x * this.y;
	}
}

然后,定义一个对象

a = new A(1, 2);

上面这句代码看起来简单,但是要和C++等面向对象的语言做个区分,A并不是严格意义上“类”的概念,因为JavaScript是没有类的,只是调用了构造函数而已。

现在问题来了,我们怎么实现继承?C++把封装,继承,多态这三个面向对象的特征实现得清清楚楚。但是对于JavaScript这样一个比较浪的语言,没有一个很严格的继承机制,而是采用以下几种方式来模拟。

0x2.JavaScript的prototype

为了能够讲清后面的apply或call函数,这里先引入prototype。prototype是只有Function才有的。

要用好继承,首先要明白为什么要设计继承这个东西?无非就是“把公共的部分”提取出来,实现代码复用。

所以在JavaScript里,也是把公共部分放在Function的prototype里。

我们来比较两个用prototype来实现继承的例子

function A(x, y) {
	this.x = x;
	this.y = y;
	this.add = function () {
		return this.x + this.y;
	}
	this.mul = function () {
		return this.x * this.y;
	}
}

function B(x,y){
	
}

B.prototype=new A(1,2);

console.log(new B(3,4).add());//3

这个例子中,子类的prototype指向一个A类对象

我们再实现一个B继承A的例子:

function A() {
	
}

A.prototype = {
	x : 1,
	y : 2,
	add : function () {
		return this.x + this.y;
	},
	mul : function () {
		return this.x * this.y;
	}
}
A.prototype.constructor=A;

function B(){
	
}

B.prototype=A.prototype;
B.prototype.constructor=B;

B的prototype对象引用了A的prototype对象,因为是引用,所以如果修改了B的prototype对象,A的prototype对象也随之修改,因为本质上他们都指向一块内存。所以每次改动B类型的prototype都要手动将constructor改回,防止错乱。相比两个例子,上一个例子因为没有引用,所以不会发生这个问题。

创建一个B类型的对象

b=new B();

b对象具有A类型的一切成员

console.log(b.add());  //3

因为每个prototype对象都有两个重要成员:constructor和_proto_,constructor本质上是一个函数指针,所以B.prototype=A.prototype执行后,覆盖掉了constructor,所以后面要让constructor重新指向B类型的构造函数。

0x3.JavaScript的构造函数绑定

在定义完一个A类型的构造函数后,再定义一个B类型,然后在B类型构造函数内部,“嵌入执行”A类型的构造函数。

function A(x, y) {
	this.x = x;
	this.y = y;
	this.add = function () {
		return this.x + this.y;
	}
	this.mul = function () {
		return this.x * this.y;
	}
}

function B(x, y, z) {
	A.apply(this, arguments);
	this.z = z;
}

console.log(new B(1,2,3));

apply函数和call函数基本一样,可以在B类型构造函数内部执行A类型构造函数。同时也可以继承A的所有成员。

显示结果:

JavaScript的继承实现小结

这里给个公式:在B构造函数里写A.apply(this),可以让B构造出来的对象可以拥有A构造函数里的所有成员。

谈到apply和call,还可以实现多重继承

function IA(){
	this.walk=function(){
		console.log("walk");
	}
}

function IB(){
	this.run=function(){
		console.log("run");
	}
}

function Person(){
	IA.apply(this);
	IB.apply(this);
}

var p=new Person();
p.walk();//walk    
p.run();
//run

 以上就是本文的全部内容了,希望大家能够喜欢

Javascript 相关文章推荐
jQuery使用手册之二 DOM操作
Mar 24 Javascript
flexigrid 类似ext grid的JS表格代码
Jul 17 Javascript
Javascript中的关键字和保留字整理
Oct 16 Javascript
js实现点击添加一个input节点
Dec 05 Javascript
javascript基本语法
May 31 Javascript
JavaScript中instanceof运算符的使用示例
Jun 08 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
Feb 03 Javascript
VUEJS 2.0 子组件访问/调用父组件的实例
Feb 10 Javascript
微信小程序实现自定义modal弹窗封装的方法
Jun 15 Javascript
微信小程序自定义组件传值 页面和组件相互传数据操作示例
May 05 Javascript
基于form-data请求格式详解
Oct 29 Javascript
微信小程序修改checkbox的样式代码实例
Jan 21 Javascript
vue2.0多条件搜索组件使用详解
Mar 26 #Javascript
Vue 进阶教程之v-model详解
May 06 #Javascript
jQuery动态追加页面数据以及事件委托详解
May 06 #jQuery
AngularJS封装$http.post()实例详解
May 06 #Javascript
JavaScript瀑布流布局实现代码
May 06 #Javascript
jquery点赞功能实现代码 点个赞吧!
May 29 #jQuery
jQuery extend()详解及简单实例
May 06 #jQuery
You might like
用sql命令修改数据表中的一个字段为非空(not null)的语句
2010/06/04 PHP
Node.js生成HttpStatusCode辅助类发布到npm
2013/04/09 Javascript
javascript实现漂亮的拖动层,窗口拖拽特效
2015/04/24 Javascript
JavaScript中使用Math.floor()方法对数字取整
2015/06/15 Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
JavaScript学习小结(一)——JavaScript入门基础
2015/09/02 Javascript
深入浅析JSON.parse()、JSON.stringify()和eval()的作用详解
2016/04/03 Javascript
AngularJs IE Compatibility 兼容老版本IE
2016/09/01 Javascript
Es6 写的文件import 起来解决方案详解
2016/12/13 Javascript
微信小程序中hidden不生效原因的解决办法
2017/04/26 Javascript
配置nodejs环境的方法
2017/05/13 NodeJs
AngularJS路由删除#符号解决的办法
2017/09/28 Javascript
node错误处理与日志记录的实现
2018/12/24 Javascript
[04:29]2014DOTA2国际邀请赛 主赛事第三日TOPPLAY
2014/07/21 DOTA
python设置windows桌面壁纸的实现代码
2013/01/28 Python
在Python中使用base64模块处理字符编码的教程
2015/04/28 Python
详解Django框架中的视图级缓存
2015/07/23 Python
Python自动化部署工具Fabric的简单上手指南
2016/04/19 Python
详解Python异常处理中的Finally else的功能
2017/12/29 Python
如何使用pyinstaller打包32位的exe程序
2019/05/26 Python
python Elasticsearch索引建立和数据的上传详解
2019/08/04 Python
python实现登录密码重置简易操作代码
2019/08/14 Python
OpenCV Python实现拼图小游戏
2020/03/23 Python
css3 transform及原生js实现鼠标拖动3D立方体旋转
2016/06/20 HTML / CSS
为有想象力的人提供的生活方式商店:Firebox
2018/06/04 全球购物
欧洲、亚洲、非洲和拉丁美洲的度假套餐:Great Value Vacations
2019/03/30 全球购物
俄罗斯购买自行车网站:Vamvelosiped
2021/01/29 全球购物
高二美术教学反思
2014/01/14 职场文书
公务员职业生涯规划书范文  
2014/01/19 职场文书
学生会离职感言
2014/02/11 职场文书
给全校老师的建议书
2014/03/13 职场文书
出售房屋委托书范本
2014/09/24 职场文书
班主任先进事迹材料
2014/12/17 职场文书
高中数学教学反思范文
2016/02/18 职场文书
《风娃娃》教学反思
2016/02/18 职场文书
用python开发一款操作MySQL的小工具
2021/05/12 Python