<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        js實現繼承的方法及優缺點總結

        來源:懂視網 責編:小采 時間:2020-11-27 21:57:25
        文檔

        js實現繼承的方法及優缺點總結

        js實現繼承的方法及優缺點總結:整理《javascript高級程序設計》中繼承的方法以及優缺點。 1. 原型鏈 ECMAScript中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。 原型鏈繼承的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。 簡單回顧一下構造函數、原
        推薦度:
        導讀js實現繼承的方法及優缺點總結:整理《javascript高級程序設計》中繼承的方法以及優缺點。 1. 原型鏈 ECMAScript中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。 原型鏈繼承的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。 簡單回顧一下構造函數、原
        function SuperType(){
         this.colors = ["red", "blue", "green"];
        }
        
        function SubType(){
        }
        //繼承了SuperType
        SubType.prototype = new SuperType();
        
        var instance1 = new SubType();
        instance1.colors.push("black");
        console.log(instance1.colors); //"red,blue,green,black"
        
        var instance2 = new SubType();
        console.log(instance2.colors); //"red,blue,green,black"

        原型鏈的第二個問題是:在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。實際上,應該說是沒有辦法在不影響所有對象實例的情況下,給超類型的構造函數傳遞參數。有鑒于此,再加上前面剛剛討論過的由于原型中包含引用類型值所帶來的問題,實踐中很少會單獨使用原型鏈

        2. 借用構造函數

        在子類型構造函數的內部調用超類型構造函數

        function SuperType() {
         this.colors = ['red', 'blue', 'green'];
        }
        function SubType() {
         SuperType.call(this);
        }
        var instance1 = new SubType();
        instance1.colors.push("black");
        console.log(instance1.colors); //"red,blue,green,black"
        
        var instance2 = new SubType();
        console.log(instance2.colors); //"red,blue,green"

        通過使用call()方法(或apply()方法也可以),我們實際上是在(未來將要)新創建的SubType實例的環境下調用了SuperType構造函數。這樣一來,就會在新SubType對象上執行SuperType()函數中定義的所有對象初始化代碼。結果,SubType的每個實例就都會具有自己的colors屬性的副本了

        對于原型鏈而言,借用構造函數有一個很大的優勢,即可以在子類型構造函數中向超類型構造函數傳遞參數

        function SuperType() {
         this.colors = ['red', 'blue', 'green'];
        }
        function SubType() {
         SuperType.call(this);
        }
        var instance1 = new SubType();
        instance1.colors.push("black");
        console.log(instance1.colors); //"red,blue,green,black"
        
        var instance2 = new SubType();
        console.log(instance2.colors); //"red,blue,green"

        借用構造函數問題:

        方法都在構造函數中定義,因此函數復用就無從談起了。而且,在超類型的原型中定義的方法,對子類型而言也是不可見的,結果所有類型都只能使用構造函數模式

        3. 組合繼承

        組合繼承(combination inheritance),有時候也叫做偽經典繼承,指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮二者之長的一種繼承模式。其背后的思路是使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。這樣,既通過在原型上定義方法實現了函數復用,又能夠保證每個實例都有它自己的屬性

        function SuperType(name){
         this.name = name;
         this.colors = ["red", "blue", "green"];
        }
        
        SuperType.prototype.sayName = function(){
         console.log(this.name);
        };
        
        function SubType(name, age){ 
        
         //繼承屬性
         SuperType.call(this, name);
         
         this.age = age;
        }
        
        //繼承方法
        SubType.prototype = new SuperType();
        SubType.prototype.sayAge = function(){
         console.log(this.age);
        };
        
        var instance1 = new SubType("Nicholas", 29);
        instance1.colors.push("black");
        console.log(instance1.colors); //"red,blue,green,black"
        instance1.sayName(); //"Nicholas";
        instance1.sayAge(); //29
        
        var instance2 = new SubType("Greg", 27);
        console.log(instance2.colors); //"red,blue,green"
        instance2.sayName(); //"Greg";
        instance2.sayAge(); //27

        組合繼承避免了原型鏈和借用構造函數的缺陷,融合了它們的優點,成為JavaScript中最常用的繼承模式。而且,instanceof和isPrototypeOf也能夠用于識別基于組合繼承創建的對象。

        無論什么情況下,都會調用兩次超類型構造函數:一次是在創建子類型原型的時候,另一次是在子類型構造函數內部

        4. 原型式繼承

        這種方法并沒有使用嚴格意義上的構造函數。借助原型可以基于已有的對象創建新對象,同時還不必因此創建自定義類型

        function object(o){
         function F(){}
         F.prototype = o;
         return new F();
        }
        var person = {
         name: "Nicholas",
         friends: ["Shelby", "Court", "Van"]
        };
        
        var anotherPerson = object(person);
        anotherPerson.name = "Greg";
        anotherPerson.friends.push("Rob");
        
        var yetAnotherPerson = object(person);
        yetAnotherPerson.name = "Linda";
        yetAnotherPerson.friends.push("Barbie");
        
        console.log(person.friends); //"Shelby,Court,Van,Rob,Barbie"

        ECMAScript 5通過新增Object.create()方法規范化了原型式繼承。這個方法接收兩個參數:一個用作新對象原型的對象和(可選的)一個為新對象定義額外屬性的對象。在傳入一個參數的情況下,Object.create()與object()方法的行為相同。
        Object.create()方法的第二個參數與Object.defineProperties()方法的第二個參數格式相同:每個屬性都是通過自己的描述符定義的。以這種方式指定的任何屬性都會覆蓋原型對象上的同名屬性

        var person = {
         name: "Nicholas",
         friends: ["Shelby", "Court", "Van"]
        };
        
        var anotherPerson = Object.create(person, {
         name: {
         value: "Greg"
         }
        });
        
        console.log(anotherPerson.name); //"Greg"

        在沒有必要興師動眾地創建構造函數,而只想讓一個對象與另一個對象保持類似的情況下,原型式繼承是完全可以勝任的。不過別忘了,包含引用類型值的屬性始終都會共享相應的值,就像使用原型模式一樣

        5. 寄生式繼承

        創建一個僅用于封裝繼承過程的函數,該函數在內部以某種方式來增強對象,最后再像真的是它做了所有工作一樣返回對象

        function createAnother(original){
         var clone = Object.create(original); //通過調用函數創建一個新對象
         clone.sayHi = function(){ //以某種方式來增強這個對象
         console.log("hi");
         };
         return clone; //返回這個對象
        }

        在這個例子中,createAnother()函數接收了一個參數,也就是將要作為新對象基礎的對象。然后,把這個對象(original)傳遞給object()函數,將返回的結果賦值給clone。再為clone對象添加一個新方法sayHi(),最后返回clone對象。可以像下面這樣來使用createAnother()函數:

        var person = {
         name: "Nicholas",
         friends: ["Shelby", "Court", "Van"]
        };
        
        var anotherPerson = createAnother(person);
        anotherPerson.sayHi(); //"hi"

        這個例子中的代碼基于person返回了一個新對象——anotherPerson。新對象不僅具有person的所有屬性和方法,而且還有自己的sayHi()方法

        使用寄生式繼承來為對象添加函數,會由于不能做到函數復用而降低效率;這一點與構造函數模式類似

        6. 寄生組合式繼承

        前面說過,組合繼承是JavaScript最常用的繼承模式;不過,它也有自己的不足。組合繼承最大的問題就是無論什么情況下,都會調用兩次超類型構造函數:一次是在創建子類型原型的時候,另一次是在子類型構造函數內部。沒錯,子類型最終會包含超類型對象的全部實例屬性,但我們不得不在調用子類型構造函數時重寫這些屬性。再來看一看下面組合繼承的例子

        function SuperType(name){
         this.name = name;
         this.colors = ["red", "blue", "green"];
        }
        
        SuperType.prototype.sayName = function(){
         console.log(this.name);
        };
        
        function SubType(name, age){ 
         SuperType.call(this, name); //第二次調用SuperType()
        
         this.age = age;
        }
        
        SubType.prototype = new SuperType(); //第一次調用SuperType()
        SubType.prototype.constructor = SubType;
        SubType.prototype.sayAge = function(){
         console.log(this.age);
        };

        在第一次調用SuperType構造函數時,SubType.prototype會得到兩個屬性:name和colors;它們都是SuperType的實例屬性,只不過現在位于SubType的原型中。當調用SubType構造函數時,又會調用一次SuperType構造函數,這一次又在新對象上創建了實例屬性name和colors,于是,這兩個屬性就屏蔽了原型中的兩個同名屬性

        如上圖所示,有兩組name和colors屬性:一組在實例上,一組在SubType原型中。這就是調用兩次SuperType構造函數的結果。好在我們已經找到了解決這個問題方法——寄生組合式繼承。

        所謂寄生組合式繼承,即通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。

        其背后的基本思路是:不必為了指定子類型的原型而調用超類型的構造函數,我們所需要的無非就是超類型原型的一個副本而已。本質上,就是使用寄生式繼承來繼承超類型的原型,然后再將結果指定給子類型的原型。寄生組合式繼承的基本模式如下所示

        function inheritPrototype(subType, superType){
         var prototype = Object.create(superType.prototype); //創建對象
         prototype.constructor = subType; //增強對象
         subType.prototype = prototype; //指定對象
        }

        這個示例中的inheritPrototype()函數實現了寄生組合式繼承的最簡單形式。這個函數接收兩個參數:子類型構造函數和超類型構造函數。在函數內部,第一步是創建超類型原型的一個副本。第二步是為創建的副本添加constructor屬性,從而彌補因重寫原型而失去的默認的constructor屬性。最后一步,將新創建的對象(即副本)賦值給子類型的原型。這樣,我們就可以用調用inheritPrototype()函數的語句,去替換前面例子中為子類型原型賦值的語句了

        function SuperType(name){
         this.name = name;
         this.colors = ["red", "blue", "green"];
        }
        
        SuperType.prototype.sayName = function(){
         console.log(this.name);
        };
        
        function SubType(name, age){ 
         SuperType.call(this, name);
        
         this.age = age;
        }
        
        inheritPrototype(SubType, SuperType);
        
        SubType.prototype.sayAge = function(){
         console.log(this.age);
        };

        這個例子的高效率體現在它只調用了一次SuperType構造函數,并且因此避免了在SubType.prototype上面創建不必要的、多余的屬性。與此同時,原型鏈還能保持不變;因此,還能夠正常使用instanceof和isPrototypeOf()。開發人員普遍認為寄生組合式繼承是引用類型最理想的繼承范式。

        總結

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        js實現繼承的方法及優缺點總結

        js實現繼承的方法及優缺點總結:整理《javascript高級程序設計》中繼承的方法以及優缺點。 1. 原型鏈 ECMAScript中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。 原型鏈繼承的基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。 簡單回顧一下構造函數、原
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲av午夜精品无码专区| 亚洲AV无码一区东京热久久| 亚洲av无码一区二区三区天堂古代| 欧洲人免费视频网站在线| 亚洲精品无码成人AAA片| 巨胸狂喷奶水视频www网站免费| 亚洲人成网站色在线入口| 免费看内射乌克兰女| 亚洲国产成人精品无码久久久久久综合 | 亚洲av日韩av无码av| 亚洲一区二区三区免费观看| 亚洲精品视频在线播放| 四虎在线免费视频| 亚洲日韩国产二区无码| 国产成人3p视频免费观看| 特级毛片A级毛片免费播放| 亚洲最大av无码网址| 西西人体免费视频| 亚洲无限乱码一二三四区| 91免费资源网站入口| 亚洲AV无码精品国产成人| 亚洲人成无码网WWW| 人妻无码久久一区二区三区免费| 亚洲视频在线观看网址| 女人被弄到高潮的免费视频 | 人妻巨大乳hd免费看| 亚洲色成人网站WWW永久| 国产在线观看免费不卡| 色www免费视频| 亚洲国产精品一区二区成人片国内| 91成人在线免费观看| 亚洲国产成人手机在线观看| 亚洲免费视频一区二区三区| 91精品导航在线网址免费| 亚洲日韩av无码中文| 国产亚洲?V无码?V男人的天堂| 51在线视频免费观看视频| 亚洲精品天堂无码中文字幕| 亚洲精品国产电影| 99精品视频免费在线观看| 日韩亚洲综合精品国产|