许多OO语言都支持两种继承方式,接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。由于在ECMAScript中,函数没有签名,无法实现接口继承,只支持实现继承,而且其实现继承主要是通过原型链来实现的。

一. 原型链模式

利用原型让引用类型继承另一个引用类型的属性和方法。

原型、构造函数和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针, 而实例包含一个指向原型对象的内部指针。

假如让原型对象等于另一个类型的实例,结果会如何?显然,此时的原型对象包好一个指向另一个原型的指针,相应地,另一个原型中也包含着指向另一个函数的指针。假如另一个原型又是另一个类型的实例,上述关系依然成立,如此层层递进,构成了实例与原型的链条。这就是所谓原型链的基本概念。

function SuperType() {
    this.superProperty = true;
}
SuperType.prototype.getSuperProperty = function() {
    console.log(this.superProperty);
};
function SubType() {
    this.subProperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubProperty = function() {
    console.log(this.subProperty);
};
var instance = new SubType();
instance.getSuperProperty();               //true

原型链模式的缺点:通过原型链实现继承时,原型实际上为另一个类型的实例,于是,原先的实例属性也变成了原型属性。而包含引用类型值的原型属性会被所有实例共享。

function SuperType() {
    this.superProperty = true;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.getSuperProperty = function() {
    console.log(this.superProperty);
};
function SubType() {
    this.subProperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubProperty = function() {
    console.log(this.subProperty);
};
var instance1 = new SubType();
instance1.colors.push("purple");
console.log(instance1.colors);            //["red", "blue", "green", "purple"]  var instance2 = new SubType();
console.log(instance2.colors);            //["red", "blue", "green", "purple"] 

为了解决原型链模式引用类型属性继承的问题,接下来讨论借用构造函数模式。

二. 借用构造函数模式

function SuperType() {
    this.colors = ["red", "blue", "green"];
}
function SubType() {
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("purple");
console.log(instance1.colors);      //["red", "blue", "green", "purple"]
var instance2 = new SubType();
console.log(instance2.colors);      //["red", "blue", "green"] 
相对于原型链,借用构造函数模式中,子类型的构造函数能够向父类型的构造函数传递参数。
function SuberType(name) {
    this.name = name;
}
function SubType(age) {
    SuberType.call(this,"Mars");
    this.age = age;
}
var instance = new SubType(27);
console.log(instance.name);            //Mars
console.log(instance.age);             //

借用构造函数模式的缺点:仅是借用构造函数,无法避免构造函数模式存在的问题——方法都在构造函数中定义,函数复用无从谈起。为解决这个问题,接下来讨论组合继承模式。

三. 组合继承

组合继承:原型链模式+借用构造函数模式,原型链模式实现对原型属性和方法的继承,借用构造函数模式实现对实例属性的继承。

function SuperType(name) {
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
    console.log(this.name);
};
function SubType(name,age) {
    SuperType.call(this,name);
    this.age = age;
}
SubType.prototype = new SuperType();
var instance1 = new SubType("Brittany",23);
instance1.colors.push("black");
console.log(instance1.colors);                  //["red", "blue", "green", "black"]
console.log(instance1.sayName());               //Brittany
var instance2 = new SubType("Closure",24);
console.log(instance2.colors);                  //["red", "blue", "green"]
console.log(instance2.sayName());               //Closure console.log(instance1 instanceof SubType);      //true
console.log(instance1 instanceof SuperType);    //true
console.log(SubType.prototype.isPrototypeOf(instance1));   //true
console.log(SuperType.prototype.isPrototypeOf(instance1)); //true

时间:2014-10-22

地点:合肥

引用:《JavaScript高级程序设计》

JavaScript 继承的更多相关文章

  1. javascript继承的三种模式

    javascript继承一般有三种模式:组合继承,原型式继承和寄生式继承: 1组合继承:javascript最为广泛的继承方式通过原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性的继承,同 ...

  2. javascript继承机制的设计思想(ryf)

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

  3. 【读书笔记】javascript 继承

    在JavaScript中继承不像C#那么直接,C#中子类继承父类之后马上获得了父类的属性和方法,但JavaScript需要分步进行. 让Brid 继承 Animal,并扩展自己fly的方法. func ...

  4. 图解JavaScript 继承

    JavaScript作为一个面向对象语言,可以实现继承是必不可少的,但是由于本身并没有类的概念(不知道这样说是否严谨,但在js中一切都类皆是对象模拟)所以在JavaScript中的继承也区别于其他的面 ...

  5. JavaScript强化教程——Cocos2d-JS中JavaScript继承

    javaScript语言本身没有提供类,没有其它语言的类继承机制,它的继承是通过对象的原型实现的,但这不能满足Cocos2d-JS引擎的要求.由于Cocos2d-JS引擎是从Cocos2d-x演变而来 ...

  6. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  7. javascript继承(六)—实现多继承

    在上一篇javascript继承—prototype最优两种继承(空函数和循环拷贝)(3) ,介绍了js较完美继承的两种实现方案,那么下面来探讨一下js里是否有多继承,如何实现多继承.在这里可以看看j ...

  8. javascript继承(五)—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承—prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

  9. javascript继承(四)—prototype属性介绍

    js里每一个function都有一个prototype属性,而每一个实例都有constructor属性,并且每一个function的prototype都有一个constructor属性,这个属性会指向 ...

  10. 【JavaScript】重温Javascript继承机制

    上段时间,团队内部有过好几次给力的分享,这里对西风师傅分享的继承机制稍作整理一下,适当加了些口语化的描述,留作备案. 一.讲个故事吧 澄清在先,Java和Javascript是雷锋和雷峰塔的关系.Ja ...

随机推荐

  1. Python进阶(三)--global和类属性

    global关键字 一句话概括为:告诉python解释器,global声明的变量为全局作用域内定义的变量.解释器就会到全局作用域内寻找global定义的变量. python的类属性 类属性相当于其他O ...

  2. 移动端web开发基础概念

    最近在了解移动端web开发的相关知识,有些概念总是模糊不清,这次花费了一些时间整体的梳理了一遍. 分辨率 分辨率可以从显示分辨率与图像分辨率两个方向来分类.显示分辨率(屏幕分辨率)是屏幕图像的精密度, ...

  3. TFS二次开发、C#知识点、SQL知识总结目录

    TFS二次开发系列 TFS二次开发系列:一.TFS体系结构和概念 TFS二次开发系列:二.TFS的安装 TFS二次开发系列:三.TFS二次开发的第一个实例 TFS二次开发系列:四.TFS二次开发Wor ...

  4. RequireJS 快速入门

      说明:本文只提供快速入门内容,方便快速进入实战状态.更高级的配置,请参考官网文档. 当初之所以使用 RequireJS 等工具,是因为想提高js的加载速度,避免不必要的堵塞.但通过一段时间的使用, ...

  5. 导出Excel和Excel生成dt

    引用ExcelLibrary.dll(qq网盘上有源代码) //导出excel,“”文件名为空时,弹出提示框 ExcelLibrary.DataSetHelper.CreateWorkbook(&qu ...

  6. <mvc:annotation-driven/>与<context:annotation-config/>的区别

    在使用注解的方式配置SSM的时候一般会配置<mvc:annotation-driven/>与<context:annotation-config/>,有时候会对两者的概念有些区 ...

  7. phalcon: 当删除循环删除一组数据,需要判断影响的行affectedRows

    phalcon:有一个表,按日期查找半年以为的数据,由于数据量特别大,不能一次:delete删除数据,否则会造成数据表卡顿,数据库锁死. 那么只能循环的删除数据,每次删除100条左右,知道删除为止., ...

  8. grunt不是内部或外部命令错误处理

    如题, npm install -g grunt-cli发现grunt命令却不可用, 其实是环境变量问题,但是网上很多给出的方法其实是不准确的, 正确方法,可以通过npm root -g查看路径,之后 ...

  9. Ubuntu16.04安装Samba

    在新装的ubuntu16.04下安装samba. 安装好samba后备份下配置文件: zhuben@zb:~$ sudo apt-get install samba zhuben@zb:~$ cd / ...

  10. 使用Kylin构建企业大数据分析平台的4种部署方式

    本篇博客重点介绍如何使用Kylin来构建大数据分析平台.根据官网介绍,其实部署Kylin非常简单,称为非侵入式安装,也就是不需要去修改已有的 Hadoop大数据平台.你只需要根据的环境下载适合的Kyl ...