详解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 相关文章推荐
JavaScript与DropDownList 区别分析
Jan 01 Javascript
jQuery Ajax提交表单查询获得数据实例代码
Sep 19 Javascript
JS动态添加与删除select中的Option对象(示例代码)
Dec 20 Javascript
jQuery知识点整理
Jan 30 Javascript
javascript对象的创建和访问
Mar 08 Javascript
jQuery插件实现图片轮播特效
Jun 16 Javascript
微信小程序 wx.request方法的异步封装实例详解
May 18 Javascript
vue.js 获取当前自定义属性值
Jun 01 Javascript
JS/HTML5游戏常用算法之碰撞检测 像素检测算法实例详解
Dec 12 Javascript
小程序绑定用户方案优化小结
May 15 Javascript
js实现金山打字通小游戏
Jul 24 Javascript
利用promise及参数解构封装ajax请求的方法
Mar 24 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下使用无限生命期Session的方法
2007/03/16 PHP
php加密解密函数authcode的用法详细解析
2013/10/28 PHP
php之curl实现http与https请求的方法
2014/10/21 PHP
php数组键名技巧小结
2015/02/17 PHP
Array的push与unshift方法性能比较分析
2011/03/05 Javascript
将两个div左右并列显示并实现点击标题切换内容
2013/10/22 Javascript
jQuery内部原理和实现方式浅析
2015/02/03 Javascript
jQuery操作JSON的CRUD用法实例
2015/02/25 Javascript
浅谈javascript中for in 和 for each in的区别
2015/04/23 Javascript
jquery获取css的color值返回RGB的方法
2015/12/18 Javascript
JS组件中bootstrap multiselect两大组件较量
2016/01/26 Javascript
jquery实现页面常用的返回顶部效果
2016/03/04 Javascript
浅析Bootstrap缩略图组件与警示框组件
2016/04/29 Javascript
Node.js + Redis Sorted Set实现任务队列
2016/09/19 Javascript
jquery  实现轮播图详解及实例代码
2016/10/12 Javascript
AngularJS获取json数据的方法详解
2017/05/27 Javascript
微信小程序开发中的疑问解答汇总
2017/07/03 Javascript
详解10分钟学会vue滚动行为
2017/09/21 Javascript
JS实现中英文混合文字溢出友好截取功能
2018/08/06 Javascript
vue-image-crop基于Vue的移动端图片裁剪组件示例
2018/08/28 Javascript
解决webpack+Vue引入iView找不到字体文件的问题
2018/09/28 Javascript
Angularjs实现数组随机排序的方法
2018/10/02 Javascript
jQuery实现B2B网站后台管理系统侧导航
2020/07/08 jQuery
python将xml xsl文件生成html文件存储示例讲解
2013/12/03 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
python range实例用法分享
2020/02/06 Python
对Python 字典元素进行删除的方法
2020/07/31 Python
拿来就用!Python批量合并PDF的示例代码
2020/08/10 Python
10个顶级Python实用库推荐
2021/03/04 Python
让IE支持HTML5的方法
2012/12/11 HTML / CSS
Onzie官网:美国时尚瑜伽品牌
2019/08/21 全球购物
数学系个人求职信范文
2014/01/30 职场文书
电子商务求职信
2014/06/15 职场文书
超市周年庆活动方案
2014/08/16 职场文书
列车乘务员工作不细心检讨书
2014/10/07 职场文书
教师考核鉴定意见
2015/06/05 职场文书