<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          六大繼承方案總結(jié)(繼承系列-3)

          共 4966字,需瀏覽 10分鐘

           ·

          2021-10-12 11:56

          目錄:

          • 原型鏈繼承

            • 問題:

          • 借用構(gòu)造函數(shù)(不算標(biāo)準(zhǔn)的繼承模式)

          • 組合繼承(偽經(jīng)典繼承)

            • 核心思想:

            • 優(yōu)點

            • 問題:(寄生組合式繼承就是為了解決這一問題)

          • 原型式繼承

            • 實現(xiàn)原理:

            • Object.create()

            • 優(yōu)點

            • 缺點

          • 寄生式繼承

            • 原理

            • 缺點

          • 寄生組合式繼承

            • 實現(xiàn)思路

            • 核心邏輯

            • 優(yōu)點

            • 圣杯模式

          原型鏈繼承和借用構(gòu)造函數(shù)繼承在前邊的篇幅都說過,本篇關(guān)于這兩個方法只是簡單過一遍。詳情請看前傳。


          原型鏈繼承

          function?SuperType()?{
          ?this.property?=?true;
          }
          SuperType.prototype.getSuperValue?=?function?()?{
          ?return?this.property;
          };
          function?SubType()?{
          ?this.subproperty?=?false;
          }
          //繼承了?SuperType?
          SubType.prototype?=?new?SuperType();
          SubType.prototype.getSubValue?=?function?()?{
          ?return?this.subproperty;
          };
          var?instance?=?new?SubType();
          alert(instance.getSuperValue());?//true

          問題:

          最主要的問題來自包含引用類型值的原型。我們前面介紹過包含引用類型值的原型屬性會被所有實例共享;而這也正是為什么要在構(gòu)造函數(shù)中,而不是在原型對象中定義屬性的原因。在通過原型來實現(xiàn)繼承時,原型實際上會變成另一個類型的實例。于是,原先的實例屬性也就順理成章地變成了現(xiàn)在的原型屬性了。

          借用構(gòu)造函數(shù)(不算標(biāo)準(zhǔn)的繼承模式)

          又叫“對象偽裝”或“經(jīng)典繼承”

          function?SuperType(name)?{
          ?this.name?=?name;
          ?this.colors?=?["red",?"blue",?"green"];
          }
          function?SubType()?{
          ?//?繼承了?SuperType?
          ?SuperType.call(this,'同時傳遞參數(shù)');
          }
          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"
          console.log(instance2.name);?//?'同時傳遞參數(shù)'

          解決了“引用類型值的原型屬性會被所有實例共享”的問題。

          組合繼承(偽經(jīng)典繼承)

          綜合了原型鏈和盜用構(gòu)造函數(shù),將兩者的優(yōu)點集中了起來。

          核心思想:

          使用借用構(gòu)造函數(shù)的技術(shù)實現(xiàn)“實例屬性”和方法的繼承,使用原型鏈實現(xiàn)“原型屬性”和方法的繼承。

          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);?//?(第一次調(diào)用構(gòu)造函數(shù))利用“借用構(gòu)造函數(shù)”的思想,繼承了SuperType實例的name,colors屬性
          ??
          ??//?自定義自己的實例屬性
          ?this.age?=?age;
          }
          SubType.prototype?=?new?SuperType();?//?(第二次調(diào)用構(gòu)造函數(shù))利用“構(gòu)造原型鏈”的思想,繼承原型屬性和方法
          SubType.prototype.constructor?=?SubType;
          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

          優(yōu)點

          ?

          組合繼承彌補了原型鏈和盜用構(gòu)造函數(shù)的不足,是 JavaScript 中使用最多的繼承模式。而且組合繼 承也保留了 instanceof 操作符和 isPrototypeOf()方法識別合成對象的能力。

          ?

          問題:(寄生組合式繼承就是為了解決這一問題)

          但依舊擁有原型繼承和借用構(gòu)造函數(shù)的缺點:

          1. 組合繼承最大的問題就是效率問題,因為無論在什么情況下,都會調(diào)用兩次構(gòu)造函數(shù):
            • 一次是在創(chuàng)建子類型原型時,
            • 另一次是在子類型構(gòu)造函數(shù)內(nèi)部。
          2. 第二個問題是會繼承多余的屬性。
            上例中,使用SubType.prototype = new SuperType();,SubType將會繼承SuperType實例對象的name、colors屬性,雖然name沒有被創(chuàng)建。因此造成了一個問題,SubType.prototype上會存在不必要的,多余的屬性。如name,colors屬性同時存在于SubType.prototype和SubType中。

          原型式繼承

          實現(xiàn)原理:

          創(chuàng)建一個臨時構(gòu)造函數(shù),將傳入的對象賦值給這個構(gòu)造函數(shù)的原型,然后返回這個臨時類型的一個實例。

          function?object(o)?{
          ??function?F()?{}
          ??F.prototype?=?o;
          ??return?new?F();
          }

          使用

          let?person?=?{
          ??name:?"Nicholas",
          ??friends:?["Shelby",?"Court",?"Van"]
          };
          let?anotherPerson?=?object(person);
          anotherPerson.name?=?"Greg";
          anotherPerson.friends.push("Rob");
          let?yetAnotherPerson?=?object(person);
          yetAnotherPerson.name?=?"Linda";
          yetAnotherPerson.friends.push("Barbie");
          console.log(person.friends);?//?"Shelby,Court,Van,Rob,Barbie"

          Object.create()

          規(guī)范化了原型式繼承的概念,用于實現(xiàn)原型式繼承

          let?person?=?{
          ??name:?"Nicholas",
          ??friends:?["Shelby",?"Court",?"Van"]
          };
          let?anotherPerson?=?Object.create(person);
          anotherPerson.name?=?"Greg";
          anotherPerson.friends.push("Rob");
          let?yetAnotherPerson?=?Object.create(person);
          yetAnotherPerson.name?=?"Linda";
          yetAnotherPerson.friends.push("Barbie");
          console.log(person.friends);?//?"Shelby,Court,Van,Rob,Barbie"

          優(yōu)點

          不需要單獨創(chuàng)建構(gòu)造函數(shù)

          缺點

          屬性中包含的引用值始終會在相關(guān)對象間共享

          寄生式繼承

          與原型式繼承比較接近,相當(dāng)于把原型式繼承又包裝了一遍。

          原理

          思路類似于寄生構(gòu)造函數(shù)和工廠模式:創(chuàng)建一個實現(xiàn)繼承的函數(shù),以某種方式增強對象,然后返回這個對象。

          基本的寄生繼承模式如下:

          function?createAnother(original)?{
          ??let?clone?=?object(original);?//?通過調(diào)用函數(shù)創(chuàng)建一個新對象?
          ??clone.sayHi?=?function?()?{?//?以某種方式增強這個對象
          ????console.log("hi");
          ??};
          ??return?clone;?//?返回這個對象?
          }

          適合主要關(guān)注對象,而不在乎類型和構(gòu)造函數(shù)的場景

          缺點

          通過寄生式繼承給對象添加函數(shù)會導(dǎo)致函數(shù)難以重用(比如上述代碼的sayHi)

          寄生組合式繼承

          實現(xiàn)思路

          寄生式組合繼承通過盜用構(gòu)造函數(shù)繼承屬性,但使用混合式原型鏈繼承方法。

          基本思路是不通過調(diào)用父類構(gòu)造函數(shù)給子類原型賦值,而是取得父類原型的一個副本。說到底就是使用寄生式繼承來繼承父類原型,然后將返回的新對象賦值給子類原型

          概括:

          1. 通過借用構(gòu)造函數(shù)來繼承屬性;
          2. 通過原型鏈來繼承方法(圣杯式繼承)。

          核心邏輯

          function?object(o)?{
          ??function?F()?{}
          ??F.prototype?=?o;
          ??return?new?F();
          }
          function?inheritPrototype(subType,?superType)?{
          ??let?prototype?=?object(superType.prototype);?//?創(chuàng)建對象?
          ??prototype.constructor?=?subType;?//?增強對象?
          ??subType.prototype?=?prototype;?//?賦值對象
          }

          這個函數(shù)接收兩個參數(shù): 子類構(gòu)造函數(shù)和父類構(gòu)造函數(shù)。

          函數(shù)內(nèi)部,第一步是創(chuàng)建父類原型的一個副本。

          給返回的 prototype 對象設(shè)置 constructor 屬性,為了解決由于重寫原型導(dǎo)致默認(rèn) constructor 丟失的問題。

          將新創(chuàng)建的對象賦值給子類型的原型。

          優(yōu)點

          只調(diào)用了一次構(gòu)造函數(shù),避免了子類原型上不必要也用不到的屬性,因此可以說這個例子的效率更高。
          而且,原型鏈仍然保持不變,因此 instanceof 操作符和 isPrototypeOf()方法正常有效。
          寄生式組合繼承可以算是引用類型繼承的最佳模式。

          圣杯模式

          最后發(fā)現(xiàn),這不就是圣杯模式的寫法么!

          function?inherit(Target,Origin){
          ?function?F(){};
          ?F.prototype?=?Origin.prototype;
          ?Target.prototype?=?new?F();
          ?Target.prototype.constuctor?=?Target;
          ?target.prototype.uber?=?Origin.prototype;
          }

          用圣杯式原型鏈繼承方法替代原來的new 構(gòu)造原型鏈的方法,這樣兒子身上就沒有父親身上的實例化屬性了!good!




          愿你歷盡千帆,歸來仍是少年。


          讓我們一起攜手同走前端路!

          關(guān)注公眾號回復(fù)【加群】即可

          ●?工作中常見頁面布局的n種實現(xiàn)方法

          ●?三欄響應(yīng)式布局(左右固寬中間自適應(yīng))的5種方法

          ●?兩欄自適應(yīng)布局的n種實現(xiàn)方法匯總

          ●?工作中常見的兩欄布局案例及分析

          ●?垂直居中布局的一百種實現(xiàn)方式

          ●?常用九宮格布局的幾大方法匯總

          ●?為什么操作DOM會影響WEB應(yīng)用的性能?

          ●?移動端滾動穿透的6種解決方案

          ●?Vue + TypeScript 踩坑總結(jié)


          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色九九影院 | 91北条麻妃二区 | 婷婷日逼网 | 国产va在线观看 国产乱伦小说视频 | www.我爱草逼 |