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 相关文章推荐
javascript中类的定义及其方式(《javascript高级程序设计》学习笔记)
Jul 04 Javascript
js 判断脚本加载完毕的代码
Jul 13 Javascript
浅析tr的隐藏和显示问题
Mar 05 Javascript
jQuery实现炫酷的鼠标轨迹特效
Feb 01 Javascript
JavaScript各类型的关系图解
Oct 16 Javascript
利用jquery给指定的table动态添加一行、删除一行的方法
Oct 12 Javascript
Javascript 判断两个IP是否在同一网段实例代码
Nov 28 Javascript
Node.js使用Express创建Web项目详细教程
Mar 31 Javascript
JavaScript实现body内任意节点的自定义属性功能示例
Sep 18 Javascript
用vue写一个仿简书的轮播图的示例代码
Mar 13 Javascript
JS实现的base64加密解密操作示例
Apr 18 Javascript
详解如何使用node.js的开发框架express创建一个web应用
Dec 20 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
php网页后退不再出现过期
2007/03/08 PHP
sphinx增量索引的一个问题
2011/06/14 PHP
真正根据utf8编码的规律来进行截取字符串的函数(utf8版sub_str )
2012/10/24 PHP
php登陆页的密码处理方式分享
2013/10/14 PHP
PHP使用NuSOAP调用Web服务的方法
2015/07/18 PHP
基于JQuery的模拟苹果桌面Dock效果(稳定版)
2012/10/15 Javascript
jquery全选/全不选/反选另一种实现方法(配合原生js)
2013/04/07 Javascript
javascript实现跳转菜单的具体方法
2013/07/05 Javascript
jquery中JSON的解析方式
2015/03/16 Javascript
教你用javascript实现随机标签云效果_附代码
2016/03/16 Javascript
javascript原生ajax写法分享
2016/04/10 Javascript
JS实用技巧小结(屏蔽错误、div滚动条设置、背景图片位置等)
2016/06/16 Javascript
原生JS实现在线问卷调查投票特效
2017/01/03 Javascript
Vue-Cli中自定义过滤器的实现代码
2017/08/12 Javascript
微信小程序网络请求封装示例
2018/07/24 Javascript
实现vuex与组件data之间的数据同步更新方式
2019/11/12 Javascript
vue通过v-html指令渲染的富文本无法修改样式的解决方案
2020/05/20 Javascript
[01:32]2014DOTA2西雅图邀请赛 CIS我们有信心进入正赛
2014/07/08 DOTA
[01:11:11]Alliance vs RNG 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
Python set集合类型操作总结
2014/11/07 Python
Python编程中的反模式实例分析
2014/12/08 Python
Python中使用dom模块生成XML文件示例
2015/04/05 Python
Python socket网络编程TCP/IP服务器与客户端通信
2017/01/05 Python
Python之日期与时间处理模块(date和datetime)
2017/02/16 Python
Python模拟鼠标点击实现方法(将通过实例自动化模拟在360浏览器中自动搜索python)
2017/08/23 Python
python射线法判断检测点是否位于区域外接矩形内
2019/06/28 Python
python按键按住不放持续响应的实例代码
2019/07/17 Python
用openCV和Python 实现图片对比,并标识出不同点的方式
2019/12/19 Python
Python面向对象原理与基础语法详解
2020/01/02 Python
keras 特征图可视化实例(中间层)
2020/01/24 Python
机电专业个人求职信范文
2013/12/30 职场文书
化工见习报告范文
2014/10/31 职场文书
2015年保安个人工作总结
2015/04/02 职场文书
仰望星空观后感
2015/06/10 职场文书
大学副班长竞选稿
2015/11/21 职场文书
css3实现背景图片颜色修改的多种方式
2021/04/13 HTML / CSS