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. ELKBR部署检测项目日志

    ELK filebeat:具有日志收集功能,相比logstash,+filebeat更轻量,占用资源更少,适合客户端使用. redis消息队列选型:Redis 服务器通常都是用作 NoSQL 数据库, ...

  2. HBase介绍、安装与应用案例

    搭建环境 部署节点操作系统为CentOS,防火墙和SElinux禁用,创建了一个shiyanlou用户并在系统根目录下创建/app目录,用于存放 Hadoop等组件运行包.因为该目录用于安装hadoo ...

  3. 通过js获取tinymce4.x的值

    问题的引出: 在使用过程中,用传统的js的方法判断tinymce所选textarea(下面直接称textarea)的值是会出现这样的问题的: 在已有输入内容时,首次提交的时候,依然会弹出js写的警告提 ...

  4. js中的几种继承方法

    JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一. 继承:子承父业:一个原本没有某些方法或属性的对象,统一写方法,拿到了另外一个对象的属性和方法 下面是js中的几种继承方式 1.改变this ...

  5. 05.Django基础五之django模型层(一)单表操作

    一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人 ...

  6. C++基础之顺序容器

    顺序容器简介: 顺序容器类型 描述 vector 可变大小数组,支持快速访问,在尾部之外的地方插入或删除时可能很慢 deque 双端队列.支持快速访问,在头尾插入删除会很快. list 双向列表.只支 ...

  7. null,undefined,undeclared的区别

    1.null表示"没有对象",即该处不应该有值,转为数值时为0.典型用法是: (1) 作为函数的参数,表示该函数的参数不是对象. (2) 作为对象原型链的终点. 2.undefin ...

  8. 夯实Java基础系列6:一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别!

    目录 抽象类介绍 为什么要用抽象类 一个抽象类小故事 一个抽象类小游戏 接口介绍 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的使用: 接口最佳实践:设计模式中的工厂模式 接 ...

  9. 【ADO.NET基础-Login】带验证码验证的登录界面(用于简单的基础学习)

    以下代码如果有不对或者不妥之处,还望大神们指点一二 或者有同学者有问题或建议,一定要提出来,共同探讨 小弟在此感谢! 前台代码: <!DOCTYPE html> <html xmln ...

  10. SUSE Linux Enterprise 15 SP1 系统安装

    从 SUSE Linux Enterprise Server 15 开始,安装媒体仅包含安装程序 - 一个用于安装.更新和注册 SUSE Linux Enterprise Server 的基于命令行的 ...