js继承机制的实现

更新日期: 2018-10-19阅读: 1.6k标签: 机制

1. 继承的概念

说明继承的最经典的例子:几何形状。实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边)。圆是椭圆的一种,它只有一个焦点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了一种完美的继承关系。

在该实例中,我想阐述的并不是继承的含义,而是说明几个关键词,即:基类 子类 超类 的含义。

在该实例中,圆形是椭圆形的子类,椭圆形是圆形的超类(父类);同样,三角形(Triangle)、矩形(Rectangle)和五边形(Pentagon)都是多边形的子类,多边形是它们的超类。



2. 继承的方式

对象冒充

    // 父类 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 具有高优先级。因为它从后面的类继承。除这点小问题之外,用对象冒充实现多重继承机制轻而易举。  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

原型链的方式

    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

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

用对象冒充的方法继承构造函数的属性,再用原型链的方式继承构造函数的方法。

    // 父类
    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

链接: https://www.fly63.com/article/detial/6057

浅析前端页面渲染机制

作为一个前端开发,最常见的运行环境应该是浏览器吧,为了更好的通过浏览器把优秀的产品带给用户,也为了更好的发展自己的前端职业之路,有必要了解从我们在浏览器地址栏输入网址到看到页面这期间浏览器是如何进行工作的

这一次,彻底弄懂 JavaScript 执行机制

javascript是一门单线程语言,Event Loop是javascript的执行机制.牢牢把握两个基本点,以认真学习javascript为中心,早日实现成为前端高手的伟大梦想!

创建js hook钩子_js中的钩子机制与实现

钩子机制也叫hook机制,或者你可以把它理解成一种匹配机制,就是我们在代码中设置一些钩子,然后程序执行时自动去匹配这些钩子;这样做的好处就是提高了程序的执行效率,减少了if else 的使用同事优化代码结构

小程序的更新机制_如何实现强制更新?

在讲小程序的更新机制之前,我们需要先了解小程序的2种启动模式,分别为:冷启动和热启动。小程序不同的启动方式,对应的更新情况不不一样的。无论冷启动,还是热启动。小程序都不会马上更新的,如果我们需要强制更新,需要如何实现呢?

基于JWT的Token认证机制实现及安全问题

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。其JWT的组成:一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。

web前端-JavaScript的运行机制

本文介绍JavaScript运行机制,JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。

轮询机制解决后端任务回调问题

现在有一个需求,前端有一个按钮,点击以后会调用后端一个接口,这个接口会根据用户的筛选条件去hadoop上跑任务,将图片的base64转为img然后打包成zip,生成一个下载连接返回给前端,弹出下载框。hadoop上的这个任务耗时比较久

JavaScript预解释是一种毫无节操的机制

js代码执行之前,浏览器首先会默认的把所有带var和function的进行提前的声明或者定义:1.理解声明和定义、2.对于带var和function关键字的在预解释的时候操作不一样的、3.预解释只发生在当前的作用域下

js对代码解析机制

脚本执行js引擎都做了什么呢?1.语法分析 2.预编译 3.解释执行。在执行代码前,还有两个步骤;语法分析很简单,就是引擎检查你的代码有没有什么低级的语法错误 ,查找全局变量声明(包括隐式全局变量声明,省略var声明),变量名作全局对象的属性,值为undefined

web认证机制

以前对认证这方面的认识一直不太深刻,不清楚为什么需要token这种认证,为什么不简单使用session存储用户登录信息等。最近读了几篇大牛的博客才对认证机制方面有了进一步了解。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!