详解JavaScript基于面向对象之继承


Posted in Javascript onDecember 13, 2015

一、面相对象继承机制
      这个实例使用UML很好的解释了继承机制。
      说明继承机制最简单的方式是,利用一个经典的例子就是几何形状。实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边)。圆是椭圆的一种,它只有一个焦点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了一种完美的继承关系,很好的解释了面向对象的继承机制。
       在这个例子中,形状是椭圆形和多边形的基类(通常我们也可以叫它父类,所有类都由它继承而来)。椭圆具有一个属(foci),说明椭圆具有的焦点的个数。圆形继承了椭圆形,因此圆形是椭圆形的子类,椭圆形是圆形的超类。同样,三角形、矩形和五边形都是多边形的子类,多边形是它们的超类。最后,正方形继承了矩形。
      最好用图来解释这种继承关系,这是 UML(统一建模语言)的用武之地。UML的主要用途之一是,可视化地表示像继承这样的复杂对象关系。下面的图示是解释形状和它的子类之间关系的UML图示:

详解JavaScript基于面向对象之继承

      在UML中,每个方框表示一个类,由类名说明。三角形 、矩形和五边形顶部的线段汇集在一起,指向形状,说明这些类都由形状继承而来。同样,从正方形指向矩形的箭头说明了它们之间的继承关系。
二、ECMAScript继承机制的实现
      要用ECMAScript实现继承机制,您可以从要继承的基类入手。所有开发者定义的类都可作为基类。出于安全原因,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击。
       选定基类后,就可以创建它的子类了。是否使用基类完全由你决定。有时,你可能想创建一个不能直接使用的基类,它只是用于给子类提供通用的函数。在这种情况下,基类被看作抽象类。尽管ECMAScript并没有像其他语言那样严格地定义抽象类,但有时它的确会创建一些不允许使用的类。通常,我们称这种类为抽象类。
      创建的子类将继承超类的所有属性和方法,包括构造函数及方法的实现。记住,所有属性和方法都是公用的,因此子类可直接访问这些方法。子类还可添加超类中没有的新属性和方法,也可以覆盖超类的属性和方法。由于JS并不是正统的面向对象语言,一些名词也需要做出改变。
三、ECMAScript继承的方式
      ECMAScript语言中将被继承的类(基类)称为超类型,子类(或派生类)称为子类型。和其他功能一样,ECMAScript实现继承的方式不止一种。这是因为JavaScript中的继承机制并不是明确规定的,而是通过模仿实现的。这意味着所有的继承细节并非完全由解释程序处理。作为开发者,你有权决定最适用的继承方式。下面为您介绍几种具体的继承方式。
(1)原型链方式
      继承这种形式在ECMAScript中原本是用于原型链的。上一篇博文已经介绍了创建对象的原型方式。原型链扩展了这种方式,以一种有趣的方式实现继承机制。prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。我们来看一个例子:

function A() {//超类型A中必须没有参数 
 this.color = "red"; 
 this.showColor = function () { 
  return this.color; 
 }; 
}; 
function B() {//子类型B 
 this.name = "John"; 
 this.showName = function () { 
  return this.name; 
 }; 
}; 
B.prototype = new A();//子类型B继承了超类型A,通过原型,形成链条 
var a = new A(); 
var b = new B(); 
document.write(a.showColor());//输出:blue 
document.write(b.showColor());//输出:red 
document.write(b.showName());//输出:John

      在原型链中,instanceof运算符的运行方式也很独特。对B的所有实例,instanceof为A和B都返回true。ECMAScript的弱类型世界中,这是极其有用的工具,不过使用对象冒充时不能使用它。例如:

var b = new B(); 
document.write(b instanceof A);//输出:true 
document.write(b instanceof B);//输出:true

       使用原型链方式实现了继承,但是这种方式无法共享和子类型给超类型传递参数。我们可以借用构造函数方式(也就是对像冒充)的方式来解决这两个问题。
(2)对象冒充方式
      对象冒充方式的其原理如下:构造函数使用this关键字给所有属性和方法赋值(即采用对象声明的构造函数方式)。因为构造函数只是一个函数,所以可使A构造函数成为B的方法,然后调用它。B就会收到A的构造函数中定义的属性和方法。例如,用下面的方式改写上面的例子创建对象A和B:
call()方法

function A(Color) {//创建超类型A 
 this.color = Color; 
 this.showColor = function () { 
   return this.color; 
 }; 
}; 
function B(Color,Name) {//创建子类型B 
 A.call(this, Color);//对象冒充,给超类型传参 
 this.name = Name;//新添加的属性 
 this.showName = 
}; 
var a = new A("blue"); 
var b = new B("red", "John"); 
document.write(a.showColor());//输出:blue 
document.write(b.showColor());//输出:red 
document.write(b.showName());//输出:John

apply()方法
和上面call()方法唯一的区别就是在子类型B中的代码:
A.call(this,arguments);//对象冒充,给超类型传参 
      当然,只有超类型中的参数顺序与子类型中的参数顺序完全一致时才可以传递参数对象。如果不是,就必须创建一个单独的数组,按照正确的顺序放置参数。
      使用对象冒充方式虽然解决了共享和传参的问题,但是没有原型,复用就更不可能了,所以我们组合上述的两种方式,即原型链方式和对象冒充的方式实现JS的继承。
(3)混合方式
      这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。由于这种混合方式使用了原型链,所以instanceof运算符仍能正确运行。
       在上一篇文章,创建对象的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法。用这两种方式重写前面的例子,代码如下:

function A(Color) { 
 this.color = Color; 
}; 
A.prototype.showColor = function () { 
 return this.color; 
}; 
function B(Color, Name) { 
 A.call(this, Color);//对象冒充 
 this.name = Name; 
}; 
B.prototype = new A();//使用原型链继承 
B.prototype.showName = function () { 
 return this.name; 
}; 
var a = new A("blue"); 
var b = new B("red", "John"); 
document.write(a.showColor());//输出:blue 
document.write(b.showColor());//输出:red 
document.write(b.showName());//输出:John

       继承的方式和创建对象的方式有一定的联系,推荐使用的继承方式还时原型链和对象冒充的混合方式。使用这种混合方式可以避免一些不必要的问题。
       看这篇文章的时候,必须看一下前面的创建对象的方式:详解JavaScript基于面向对象之创建对象(1)详解JavaScript基于面向对象之创建对象(2)

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
多个iframe自动调整大小的问题
Sep 18 Javascript
event.srcElement 用法笔记e.target
Dec 18 Javascript
parseInt parseFloat js字符串转换数字
Aug 01 Javascript
jQuery菜单插件superfish使用指南
Apr 21 Javascript
深入学习JavaScript中的Rest参数和参数默认值
Jul 28 Javascript
JS实现复制内容到剪贴板功能兼容所有浏览器(推荐)
Jun 17 Javascript
Angularjs 自定义服务的三种方式(推荐)
Aug 02 Javascript
Bootstrap模态框水平垂直居中与增加拖拽功能
Nov 09 Javascript
bootstrapValidator 重新启用提交按钮的方法
Feb 20 Javascript
详解Node.js access_token的获取、存储及更新
Jun 20 Javascript
微信小程序3种位置API的使用方法详解
Aug 05 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
Feb 09 Javascript
轻松使用jQuery双向select控件Bootstrap Dual Listbox
Dec 13 #Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
Dec 13 #Javascript
推荐阅读的js快速判断IE浏览器(兼容IE10与IE11)
Dec 13 #Javascript
JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
Dec 13 #Javascript
javascript性能优化之DOM交互操作实例分析
Dec 12 #Javascript
JavaScript文档碎片操作实例分析
Dec 12 #Javascript
javascript性能优化之事件委托实例详解
Dec 12 #Javascript
You might like
Apache2 httpd.conf 中文版
2006/11/17 PHP
PHP Ajax实现无刷新附件上传
2016/08/17 PHP
PHP defined()函数的使用图文详解
2019/07/20 PHP
JavaScript入门教程(3) js面向对象
2009/01/31 Javascript
JQuery 小练习(实例代码)
2009/08/07 Javascript
23个超流行的jQuery相册插件整理分享
2011/04/25 Javascript
使用GruntJS链接与压缩多个JavaScript文件过程详解
2013/08/02 Javascript
javascript firefox 自动加载iframe 自动调整高宽示例
2013/08/27 Javascript
使用js检测浏览器是否支持html5中的video标签的方法
2014/03/12 Javascript
修改或扩展jQuery原生方法的代码实例
2015/01/13 Javascript
JavaScript控制网页层收起和展开效果的方法
2015/04/15 Javascript
jQuery插件实现带圆点的焦点图片轮播切换
2016/01/18 Javascript
利用jQuery设计一个简单的web音乐播放器的实例分享
2016/03/08 Javascript
JS结合bootstrap实现基本的增删改查功能
2016/07/22 Javascript
jQuery插件zTree实现获取一级节点数据的方法
2017/03/08 Javascript
详解jquery插件jquery.viewport.js学习使用方法
2017/09/08 jQuery
JS设计模式之状态模式概念与用法分析
2018/02/05 Javascript
逐行分析鸿蒙系统的 JavaScript 框架(推荐)
2020/09/17 Javascript
一篇不错的Python入门教程
2007/02/08 Python
Python3中多线程编程的队列运作示例
2015/04/16 Python
python实现淘宝秒杀聚划算抢购自动提醒源码
2020/06/23 Python
[原创]Python入门教程5. 字典基本操作【定义、运算、常用函数】
2018/11/01 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
Python实现微信中找回好友、群聊用户撤回的消息功能示例
2019/08/23 Python
python垃圾回收机制(GC)原理解析
2019/12/30 Python
基于Python正确读取资源文件
2020/09/14 Python
python 爬取腾讯视频评论的实现步骤
2021/02/18 Python
意大利团购网站:Groupon意大利
2016/10/11 全球购物
Parfume Klik丹麦:香水网上商店
2018/07/10 全球购物
天网面试题
2013/04/07 面试题
初入社会应届生求职信
2013/11/18 职场文书
转让协议书范本
2014/09/13 职场文书
党的群众路线教育实践活动整改方案
2014/10/28 职场文书
街道社区活动报告
2015/02/05 职场文书
医院党建工作总结2015
2015/05/26 职场文书
2016教师给学生的毕业寄语
2015/12/04 职场文书