详解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 相关文章推荐
WordPress 插件——CoolCode使用方法与下载
Jul 02 Javascript
jQuery学习3:操作元素属性和特性
Feb 07 Javascript
javascript函数定义的几种区别小结
Jan 06 Javascript
JQuery中serialize()、serializeArray()和param()方法示例介绍
Jul 31 Javascript
JavaScript学习笔记之内置对象
Jan 22 Javascript
JavaScript中数据结构与算法(二):队列
Jun 19 Javascript
基于JavaScript实现仿京东图片轮播效果
Nov 06 Javascript
Bootstrap创建可折叠的组件
Feb 23 Javascript
js禁止Backspace键使浏览器后退的实现方法
Sep 01 Javascript
Vue 2.0入门基础知识之内部指令详解
Oct 15 Javascript
JavaScript实现音乐自动切换和轮播
Nov 05 Javascript
详解JavaScript实现动态的轮播图效果
Apr 29 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
php中解析带中文字符的url函数分享
2015/01/20 PHP
PHP实现的自定义数组排序函数与排序类示例
2016/11/18 PHP
php查询及多条件查询
2017/02/26 PHP
PHP 断点续传实例详解
2017/11/11 PHP
js 数组操作之pop,push,unshift,splice,shift
2014/01/29 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
2016/03/04 Javascript
jQuery插件制作的实例教程
2016/05/16 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
2016/11/18 Javascript
angular实现商品筛选功能
2017/02/01 Javascript
详解Angular2中Input和Output用法及示例
2017/05/21 Javascript
js 开发之autocomplete="off"在chrom中失效的解决办法
2017/09/28 Javascript
JavaScript如何获取到导航条中HTTP信息
2017/10/10 Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
2018/08/10 Javascript
详解如何配置vue-cli3.0的vue.config.js
2018/08/23 Javascript
JavaScript实现拖动对话框效果的实现代码
2020/10/12 Javascript
[01:52]DOTA2完美大师赛Vega战队趣味视频——kpii老师小课堂
2017/11/25 DOTA
python与php实现分割文件代码
2017/03/06 Python
详解Python装饰器
2019/03/25 Python
selenium+python自动化测试环境搭建步骤
2019/06/03 Python
Python 函数绘图及函数图像微分与积分
2019/11/20 Python
Python scrapy爬取小说代码案例详解
2020/07/09 Python
python中pyplot基础图标函数整理
2020/11/10 Python
英国著名的茶叶品牌:Whittard of Chelsea
2016/09/22 全球购物
ECCO爱步加拿大官网:北欧丹麦鞋履及皮具品牌
2017/07/08 全球购物
法国二手MacBook销售网站:Okamac
2019/03/18 全球购物
介绍下Java的输入输出流
2014/01/22 面试题
个人简历自荐信
2013/12/05 职场文书
优秀共产党员演讲稿
2014/09/04 职场文书
工作证明英文模板
2014/10/21 职场文书
食品药品安全责任书
2015/05/11 职场文书
2015社区健康教育工作总结
2015/05/20 职场文书
2019奶茶店创业计划书范本,值得你借鉴
2019/08/14 职场文书
小学语文的各类谚语(70首)
2019/08/15 职场文书
如何在pycharm中快捷安装pip命令(如pygame)
2021/05/31 Python
Python中的pprint模块
2021/11/27 Python