首頁 >web前端 >js教程 >javascript的繼承方式有哪些

javascript的繼承方式有哪些

王林
王林原創
2021-07-12 13:50:581675瀏覽

javascript中的繼承方式有原型鏈繼承、借用建構函式繼承、組合繼承、原型式繼承、寄生式繼承和寄生組合式繼承。其中組合繼承是我們平常最常用的一種繼承方式。

javascript的繼承方式有哪些

本文操作環境:windows10系統、javascript 1.8.5、thinkpad t480電腦。

在javascript中如果想要繼承,那麼我們就必須先提供一個父類,我們這裡以Person來當父類別。

下文中所有建構函式名稱均無實際意義,如Coder、Rocker等,僅用於舉例

		 function Person(name){//给构造函数添加了参数
		            this.name=name;
		            this.sex="male";
		            this.say=function(){
		                console.log(this.name);
		            }
		        }
		Person.prototype.age=21;//给构造函数添加了原型属性

#一、原型鏈繼承##

		function Programmer(){
            this.name="Jayee";
        }

        Programmer.prototype=new Person();//子类构造函数.prototype=父类实例

        var per1=new Programmer();
        console.log(per1);//Programmer {name: "Jayee"}
        console.log(per1.sex);//male
        console.log(per1.age);//21
        console.log(per1 instanceof Person);//true

重點:讓新實例的原型等於父類別的實例。 Programmer.prototype=new Person();

特點:實例可繼承的屬性有:實例的建構子的屬性,父類別建構子屬性,父類別原型 的 屬性。 (新實例不會繼承父類別實例的屬性!)

缺點:1、新實例無法向父類別建構子傳參。

   2、繼承單一。

   3、所有新實例都會共用父類別實例的屬性。 (原型上的屬性是共享的,一個實例修

    改變了原型的屬性(per1.__proto__.sex=“female”,則per2.sex也會變成female),另

    一個實例的原型屬性也會被修改!)

二、借用建構子繼承

        //借用构造函数继承
        function Coder(){
            Person.call(this,"Jayee");//重点:借用了Person
            this.age=18;
        }
        var cod1=new Coder();
        console.log(cod1);
        //Coder {name: "Jayee", sex: "male", hobby: "", age: 18, say: ƒ}
        console.log(cod1.name);//Jayee
        console.log(cod1.age);//18
        console.log(cod1 instanceof Person);//false

重點:用.call()和.apply()將父類別建構子引入子類別函數(在子類別函數中做了父類別函數的自執行(複製))

特徵:1、只繼承了父類別建構子的屬性,沒有繼承父類別原型的屬性。 (由

    cod1.age是18而不是21可看出)

   2、解決了原型鏈繼承缺點1、2、3。

   3、可以繼承多個建構子屬性(call多個)。

   4、在子實例中可傳參父實例。

缺點:1、只能繼承父類別建構子的屬性。

   2、無法實現建構子的複用。 (每次用每次都要重新呼叫)

   3、每個新實例都有父類別建構子的副本,臃腫。

三、組合繼承(組合原型鏈繼承和借用建構子繼承)(常用)

        //组合继承
        function Typer(name){
            Person.call(this,name);
        }
        Typer.prototype=new Person();
        var typ=new Typer("Jayee");
        console.log(typ);
        //Typer {name: "Jayee", sex: "male", hobby: "", say: ƒ}
        console.log(typ.name);//Jayee,继承了构造函数
        console.log(typ.age);//21,继承了父类的原型的属性

重點:結合了兩種模式的優點,傳參和重複使用

特點:1、可以繼承父類別原型上的屬性,可以傳參,可重複使用。

   2、每個新實例所引入的建構子屬性是私有的。

缺點:呼叫了兩次父類別建構子(耗記憶體),子類別的建構子會取代原型上的那

   個父類別建構子

四、原型式繼承

        //原型式继承
        function Rocker(obj) {
        //先封装一个函数容器,用来输出对象和承载继承的原型
            function F(){}
            F.prototype=obj;//继承了传入的函数
            return new F();//返回函数对象
        }
        var per=new Person();//拿到父类实例
        var roc =Rocker(per);//F {}
        console.log(per.__proto__);//{age: 21, constructor: ƒ}
        console.log(roc.age);//21,继承了父类函数的属性

重點:用一個函數包裝一個對象,然後返回這個函數的調用,這個函數就變成了一個可以隨

#意增添屬性的實例或對象。 object.create()就是這個原理。

特點:類似複製一個對象,用函數來包裝。

缺點:1、所有實例都會繼承原型上的屬性。

   2、無法實現復用。 (新實例屬性都是後面新增的)

五、寄生式繼承

        //寄生式继承
        function Rocker(obj){
            function F(){}
            F.prototype=obj;//继承了传入的函数
            return new F();//返回函数对象
        }
        var per4=new Person();
        //以上是原型式继承,给原型式继承再套个壳子传递参数
        function Artist(obj){
            var roc=Rocker(obj);
            roc.name="Jayee";
            return roc;
        }
        var art = Artist(per4)
        //这个函数经过声明之后就成了可增添属性的对象
        console.log(typeof Artist);//function
        console.log(typeof art);//object
        console.log(art.name);//Jayee,返回了个roc对象,继承了roc的属性

重點:就是給原型式繼承外面套了個殼子。

優點:沒有建立自訂類型,因為只是套了個殼子回傳物件(這個),這個函數順理成章就成了創建的新物件。

缺點:沒用到原型,無法重複使用。

六、寄生組合式繼承(常用)

寄生:在函數內回傳物件然後呼叫

組合:1、函數的原型等於另一個實例。 2.在函數中用apply或call引入另一個建構函數,可傳參

         //寄生式组合式继承

         //寄生
         function Rocker(obj){
            function F(){}
            F.prototype=obj;//继承了传入的函数
            return new F();//返回函数对象
        }
        //Rocker就是F实例的另一种表示法
        var roc=new Rocker(Person.prototype);
        //roc实例(F实例)的原型继承了父类函数的原型
        //上述更像是原型链继承,只不过继承了原型属性

        //组合
        function Sub(){
            Person.call(this);
            //这个继承了父类构造函数的属性
            //解决了组合式两次调用构造函数属性的缺点
        }
        //重点
        Sub.prototype=roc;//继承了roc实例
        roc.constructor=Sub;//一定要修复实例
        var sub1=new Sub();
        //Sub的实例就继承了构造函数属性,父类实例,roc的函数属性
        console.log(sub1.age);//21

重點:修正了組合繼承的問題

七、ES6中的Class和extends

#

//todo

相關影片教學分享:

javascript影片教學#

以上是javascript的繼承方式有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn