• JavaScript的继承


    之前遇到过一道题:说什么是js的混合继承?无知的我以为是:对象自身属性和原型上方法的继承。妥妥的打脸啊[捂脸](写完这篇文章后,发现我这个说法好像也是没啥毛病啊,混合继承就是用对象冒充来继承另外一个构造函数的自身属性,改写对象prototype指向另外一个对象,就是对象自身属性和原型的继承嘛[捂脸])

    那么首先来说说继承机制的实现方式吧:

    首先是基类的创建,再就是子类的创建,创建的子类将继承超类的所有属性和方法,包括构造函数以及方法的实现。所有属性和方法都是公用的,因此子类可以直接访问这些方法。子类还可以添加超类中没有的新属性和方法,也可以覆盖超类的属性和方法。

    javascript中继承的方式:

    1.对象冒充

    原理:构造函数使用 this 关键字给所有属性和方法赋值,所以可使ClassA 构造函数成为ClassB的方法,然后调用它,ClassB就会收到ClassA中定义的属性和方法。例如:

    function ClassA(sColor){
        this.color = sColor;
        this.sayColor = function(){
            alert(this.color);
        }
    }
    function ClassB(sColor,sName){
        this.newMethod = ClassA;
        this.newMethod(sColor);
        delete this.newMethod;
        this.sayName = function(){
            alert(sName);
        }
    }
    
    var objA = new ClassA("blue");
    var objB = new ClassB("red","miya");
    objA.sayColor();   //blue
    objB.sayColor();   //red
    objB.sayName();    //miya

    ClassA赋予了方法newMethod(函数名只是指向它的指针),然后调用该方法,传递给的是ClassB的参数sColor,所有新属性和新方法都必须在删除了新方法的代码行后定义,否则可能会覆盖超类的相关属性和方法。

    对象冒充可以实现多重继承

    一个类可以继承多个超类。如果存在两个类ClassX和ClassY具有同名的属性或者方法,下面的ClassY具有更高的优先级。所以多个对象继承时候注意下属性方法的覆盖。

    在javascript中call()和apply()就是对象冒充最为相似的方法。

    function sayColor(f){
        console.log(`${f} ${this.color}`);
    }
    var obj =  new Object();
    obj.color = 'green';
    sayColor.call(obj,'I like')   //I like green

    sayColor()里面的this关键字指向obj,对象冒充和继承机制一起使用,如下:

    function ClassA(sColor){
        this.sayColor = function(){
            alert(sColor);
        }
    }
    function ClassB(sColor,sName){
        ClassA.call(this,sColor);
        this.name = sName;
        this.sayName = function(){
            alert(this.name);
        }
    }
    var c = new ClassB('green','miya');
    c.sayColor() //green
    c.sayName() //miya

    ClassB继承了ClassA的方法。apply和call作用相同,只是传参形式不同,apply传递的是数组形式的。

    2.原型链的继承

    prototype是个模板,要实例化的对象都以这个模板为基础,prototype对象的任何属性和方法都被传递给那个类的所有实例。 

    ClassB.prototype = new ClassA();

     将ClassB的原型指向了一个ClassA的实例对象上,所以,ClassB的 原型就是ClassA的实例对象。

    var objB = new ClassB();
    objB instanceof ClassA
    //true
    objB instanceof ClassB
    //true

    原型链的弊端:不支持多重继承,会重写类的prototype属性。

    3,混合方式继承

    终于说到话题最开始的时候了,什么是混合继承?

    使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,如果使用原型链就无法使用带参数的构造函数,对象冒充和原型链继承方式都用,就是混合继承。

    创建类最好的方式:用构造函数定义属性,用原型定义方法。

    混合继承就是:用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法。

    function ClassA(scolor){
        this.color = scolor;
    }
    ClassA.prototype.sayColor = function(){
        console.log(this.color);
    }
    function ClassB(scolor,sname){
        ClassA.call(this,scolor);
        this.name = sname;
    }
    ClassB.prototype = new ClassA();
    ClassB.prototype.sayName = function(){
        console.log(this.name);
    }
    var objA = new ClassA("blue");
    var objB = new ClassB("red","miya");
    objA.sayColor();  //blue
    objB.sayColor();  //red
    objB.sayName(); //miya

    objA instanceof ClassA     //true
    objB instanceof ClassA     //true
    objB instanceof ClassB      //true

    在该例子中,继承的突出在于,ClassB构造函数中,用对象冒充继承了ClassA的自身属性,将ClassB的原型对象指向了ClassA的实例对象上面,然后再在原型上面添加新的方法。
    因为使用了原型链,所以可以使用instanceof进行测试:对象是否继承某个类的原型

  • 相关阅读:
    Error: bzip2: Compressed file ends unexpectedly; # perhaps it is corrupted?
    诡异shellbash脚本没写错运行的时候不报错也不执行
    seeksv
    常用Linux对脚本的基本操作——持续更新
    lumpy-sv
    常用linux对系统的基本操作——持续更新
    常用linux对文件的基本操作——持续更新
    css浮动与定位
    CSS知识点概要
    HTML5新手入门基础知识要点概要
  • 原文地址:https://www.cnblogs.com/tangjiao/p/8964390.html
Copyright © 2020-2023  润新知