js继承机制的实现


1. 继承的概念

  1. 说明继承的最经典的例子:几何形状。实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边)。圆是椭圆的一种,它只有一个焦点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了一种完美的继承关系。
  2. 在该实例中,我想阐述的并不是继承的含义,而是说明几个关键词,即:基类 子类 超类 的含义。
  3. 在该实例中,圆形是椭圆形的子类,椭圆形是圆形的超类(父类);同样,三角形(Triangle)、矩形(Rectangle)和五边形(Pentagon)都是多边形的子类,多边形是它们的超类。


2. 继承的方式

  1. 对象冒充
    // 父类 ClassA
function ClassA(aColor){
this.color = aColor;
this.showColor = function(){
console.log(this.color);
}
}
// 子类 ClassB
function ClassB(bColor,bName){
this.newMethod = ClassA; // 函数名ClassA只是指向函数的指针,所以这里是将this.newMethod也指向ClassA这个函数,所以函数ClassB就拥有了函数ClassA的方法和属性
this.newMethod(bColor);
delete this.newMethod; // 该操作使得实例化的对象不需要多次继承同一个函数了,因为继承一次就可以了。注意:新增的属性和方法最好都写在 删除对另一个函数引用的后面,因为如果在前面定义的话,如果父类刚好有该属性或者方法你就会把父类的属性和方法 给覆盖掉。
this.name = bName;
this.sayName = function(){
console.log(this.name);
}
}
// --------------------------------------
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.showColor(); // blue
objB.showColor(); // red
objB.sayName(); // John
  • 对象冒充还可以实现多重继承

    例如,如果存在两个类 ClassX 和 ClassY,ClassZ 想继承这两个类,可以使用下面的代码:
    function ClassZ() {
this.newMethod = ClassX;
this.newMethod();
delete this.newMethod; this.newMethod = ClassY;
this.newMethod();
delete this.newMethod;
}
   这里存在一个弊端,如果存在两个类 ClassX 和 ClassY 具有同名的属性或方法,ClassY 具有高优先级。因为它从后面的类继承。除这点小问题之外,用对象冒充实现多重继承机制轻而易举。

  1. call、apply方法(和对象冒充类似)

    call、apply这两个方法的使用方法和原理在上一个博客写了,可以去参考一下
    // call方法
function ClassA(acolor){
this.color = acolor;
this.showColor = function(){
console.log(this.color);
}
}
function ClassB(bcolor){
ClassA.call(this,bcolor); // 这里的this指的是ClassB实例化的对象,让this调用函数ClassA,达到继承效果。第二个参数是对应ClassA的参数
}
var objA = new ClassA('blue');
var objB = new ClassB('red');
objA.showColor(); // blue
objB.showColor(); // red
    function ClassA(acolor){
this.color = acolor;
this.showColor = function(){
console.log(this.color);
}
}
function ClassB(bcolor){
// ClassA.apply(this,Array(bcolor));
ClassA.apply(this, arguments); // 这里使用上面的或者arguments都可以,arguments代表的是实参的类数组对象
}
var objA = new ClassA('blue');
var objB = new ClassB('red');
objA.showColor(); // blue
objB.showColor(); // red

  1. 原型链的方式
    function ClassA() {}

    ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
alert(this.color);
}; function ClassB() {} ClassB.prototype = new ClassA(); // 这是关键

原型方式的神奇之处在于“ClassB.prototype = new ClassA()”代码行。这里,把 ClassB 的 prototype 属性设置成 ClassA 的实例。这很有意思,因为想要 ClassA 的所有属性和方法,但又不想逐个将它们 ClassB 的 prototype 属性进行手动链接。还有比把 ClassA 的实例赋予 prototype 属性更好的方法吗?

与对象冒充相似,子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。所以,为 ClassB 类添加 name 属性和 sayName() 方法的代码如下:

    function ClassB() {
} ClassB.prototype = new ClassA(); ClassB.prototype.name = "zjy";
ClassB.prototype.sayName = function () {
alert(this.name);
};

测试代码如下:

    var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "red";
objB.name = "John";
objA.sayColor(); // blue
objB.sayColor(); // red
objB.sayName(); // John

  1. 原型链和对象冒充混合使用

    用对象冒充的方法继承构造函数的属性,再用原型链的方式继承构造函数的方法。
    // 父类
function ClassA(acolor){// 之所以方法通过原型链来定义是因为方法多数都是对象共享的,如果放在构造函数内部的话,多个实例化对象就会产生多个同样的方法,所以为了减少这样的浪费,将方法通过原型链定义,这样即满足了共享的原则也实现了重复利用不会浪费。不管在内部定义方法还是通过原型链定义,都可以通过其他构造函数的原型链继承到。
this.color = acolor;
}
ClassA.prototype.showColor = function(){ //属性在构造函数内定义,方法通过原型定义
console.log(this.color);
}
// 子类
function ClassB(bcolor,name){
ClassA.call(this,bcolor); // 通过call()对象冒充的方式继承构造函数的属性
this.name = name;
}
ClassB.prototype = new ClassA(); // 通过原型链的方式继承构造函数的方法
ClassB.prototype.showName = function(){
console.log(this.name);
}

测试代码如下:

    var objA = new ClassA('blue');
var objB = new ClassB('red','tom');
objA.showColor(); // blue
objB.showColor(); // red
objB.showName(); // tom

本博客参考了w3cschool相关的解释和代码,链接地址如下 w3cschool

js继承机制的实现的更多相关文章

  1. Javascript 构造函数原型继承机制

    我们先聊聊Js的历史,1994年Netscape公司发布了Navigator浏览器0.9班.这是历史上第一个比较成熟的网络浏览器.轰动一时.但是,这个版本的浏览器只能用来浏览,不具备交互功能,最主要的 ...

  2. js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } Class ...

  3. js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } ClassA ...

  4. 27、理解js的继承机制(转载自阮一峰)

    Javascript继承机制的设计思想   作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...

  5. js继承相关

    这几天看到一篇文章详解Javascript的继承实现,发现js还是很深奥的,比如call.apply.prototype这些,问起来我也能说的头头是道的,但是看到一些复杂的代码有的时候还是会迷糊,所以 ...

  6. Javascript类继承-机制-代码Demo【原创】

    最近看到<Javascript设计模式>,对js模拟的”继承方式“有了更深一步的了解,虽然之前也总是用到prototype.new ,但只是知其然不知所以然,现在将类继承的方法整理如下,暂 ...

  7. js继承的常用方法

    写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...

  8. JavaScript 原型与继承机制详解

    引言 初识 JavaScript 对象的时候,我以为 JS 是没有继承这种说法的,虽说 JS 是一门面向对象语言,可是面向对象的一些特性在 JS 中并不存在(比如多态,不过严格来说也没有继承).这就困 ...

  9. JS继承的从入门到理解

    开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什 ...

随机推荐

  1. MyBatis的发展和选型

    xlecho编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! 参考 ...

  2. 新书推荐《再也不踩坑的Kubernetes实战指南》

      <再也不踩坑的Kubernetes实战指南>终于出版啦.目前可以在京东.天猫购买,京东自营和当当网预计一个星期左右上架. 本书贴合生产环境经验,解决在初次使用或者是构建集群中的痛点,帮 ...

  3. Spring Cloud同步场景分布式事务怎样做?试试Seata

    一.概述 在微服务架构下,虽然我们会尽量避免分布式事务,但是只要业务复杂的情况下这是一个绕不开的问题,如何保证业务数据一致性呢?本文主要介绍同步场景下使用Seata的AT模式来解决一致性问题. Sea ...

  4. Android开发中常用Dialog(普通弹窗&时间选择器&日历选择器)

    引言 开发中,我们会有很多地方使用 Dialog 来展示一些提示信息或设置信息.如:用户提示.进度展示.时间设置.日期设置等. 下面我和大家一些学习下Android中常用的几种Dialog吧~ * 首 ...

  5. Hadoop 之 MapReduce原理

    1.什么是MapReduce 答:简而言之,就是将一个大任务分成多个小的子任务(Map),并行执行后,合并结果(Reduce).下面举一个纸牌得栗子  2.MapReduce的运行流程  3.JobT ...

  6. 制作mysql大数据表验证覆盖索引

    昨天跟同事聊起数据表性能的问题,能不能仅用覆盖索引实现数据的汇总统计.找了一个开发环境已有的数据表进行测试,通过explain命令,能看到mysql通过覆盖索引就能实现sum的需求,而无须去读取实际行 ...

  7. JavaScript之数据类型转换

    JavaScript中有多种数据类型,在实际工作中,不管是有意还是无意的,我们总能碰到不一样的数据类型值之间进行运算,或者我想从用户输入获得一个数字时,而用户却输入了一个字符串,这种时候就需要用到今天 ...

  8. pt-table-sync 配合pt-table-checksum 修复主从不一致

    pt-table-sync 配合pt-table-checksum 修复主从不一致. 先执行下面这条语句,打印出要执行的命令,确认无误后再将  --print  改为  --execute 执行.注意 ...

  9. numpy库使用总结

    numpy study 0x01:n维数组对象ndaarray 存放同类型元素的多维数组 0x02:numpy数据类型 numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 ...

  10. tomcat下c3p0连接池配置问题

    一.首先如果要使用这个连接池,就需要导入c3p0-0.9.2-pre1.jar架包和支持架包mchange-commons-0.2.jar, 我这里测试使用的是msql数据库 当然也需要导入mysql ...