<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 6.3 繼承 由于函數沒有簽名,在ECMAScript中無法實現接口繼承,ECMAScript只支持**實現繼承**,而且其實現繼承主要是依靠**原型鏈**來實現的。 ### 6.3.1 原型鏈 基本思想:利用原型讓一個引用類型繼承另一個引用類型。 ~~~ function SuperType(){ this.property = true; } SuperType.property.getSuperValue = function(){ return this.property; } function SubType(){ this.subproperty = false; } SubType.prototype = new SuperType(); //繼承了SuperType SubType.prototype.getSubValue = function(){ return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue) //true ~~~ 此時`instance.constructor`現在指向的是`SuperType`,這是因為`SubType`的原型指向了另一個對象`SuperType的原型`,而這個原型對象的constructor屬性指向的是SuperType。 **1. 別忘記默認的原型** 所有函數的默認原型都是Object的實例,因此默認原型都會包含一個**內部指針**,指向`Object.prototype`,這正是所有自定義類型都會繼承toString()、valueOf等默認方法的根本原因。 **2. 確定原型和實例的關系** 通過兩種方式來確定原型與實例之間的關系。第一種方式是使用`instanceof`操作符;第二種方式是使用`isPrototypeOf()`方法。 ~~~ alert(SubType.prototype.isPrototypeOf(instance)); //true; ~~~ **3. 謹慎地定義方法** 給原型添加方法的代碼一定要放在**替換**原型的語句**之后**。 提醒:在通過原型鏈實現繼承時,不能使用對象字面量創建原型方法,因為這樣會**重寫原型鏈**。 **4. 原型鏈的問題** * 包含引用類型值的原型,其屬性會被所有實例共享。 * 在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。 ### 6.3.2 借用構造函數(偽構造對象或經典繼承) **基本思想:在子類型構造函數的內部調用超類型構造函數。** ~~~ function SuperType(){ this.colors = ['red','yellow','blue']; } function SubType(){ SuperType.call(this); //繼承SuperType } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green" ~~~ 通過使用`call()或者apply()`方法,我們實際上是在(未來將要)創建的SubType實例的環境下調用了SuperType構造函數。這樣一來,就會在新SubType()對象上執行SuperType()函數中定義的所有對象初始化代碼。結果,SubType的每個實例就都會具有自己的colors屬性的副本。 **1. 傳遞參數** 相對于原型鏈而言,借用構造函數有一個很大的優勢,即**可以在子類型構造函數中向超類型構造函數傳遞參數。** ~~~ function SuperType(name){ this.name = name; } function SubType(){ SuperType.call(this,'ken'); this.age = 28; } ~~~ **2. 借用構造函數的問題** * 方法都在構造函數中定義,無法函數復用 * 在超類型的原型中定義的方法(使用prototype定義的),對于子類型而言也是不可見的,結果所有類型都只能使用構造函數模式。 ### 6.3.3 組合繼承(偽經典繼承) 思路:**使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承**。這樣,既在原型上定義方法實現了函數復用,又能夠保證每個實例都有自己的屬性。 ~~~ function SuperType(name){ this.name = name; this.colors = ['red','blue'.'green]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,age) { //繼承屬性 SuperType.call(this,name); this.age = age; } //繼承方法 SubType.prototype = new SuperType(); //將SuperType的實例復制給SubType的原型 SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType('ken',28); instance1.colors.push('black); alert(instance1.colors); //'red,blue,green,black' instance1.sayName(); //'ken' instance1.sayAge(); //28 var instance2 = new SubType('Greg',27); alert(instance2.colors); //'red,blue,green' instance2.sayName(); //'Greg' instance2.sayAge(); //27 ~~~ 組合繼承避免了原型鏈和借用構造函數的缺陷,融合了他們的優點,成為JavaScript中最常用的繼承模式。而且,instanceof和isPrototypeOf()也能夠用于識別基于組合繼承創建的對象。 **缺點**:由于多次調用超類型構造函數而導致低效率。 ### 6.3.4 原型式繼承 原型式繼承沒有嚴格意義上的使用構造函數,它是借助原型可以基于已有的對象創建新對象,同時還不必因此創建自定義類型。 ~~~ function object(o){ function F(){} F.prototype = o; return new F(); } ~~~ 在object()函數內部,先創建了一個臨時性的構造函數,然后將傳入的對象作為這個構造函數的原型,最后返回這個臨時類型的新實例。從本質上講,object()對傳入其中的對象執行了一次**淺復制**。例: ~~~ var person = { name: 'Nicholas', friends: ['wesley','fox'] }; var anotherPerson = object(person); anotherPerson.name = 'Greg'; anotherPerson.friends.push('Rob'); var yetAnotherPerson = object(person); yetAnotherPerson.name = 'Linda'; yetAnotherPerson.friends.push('Barbie'); alert(person.friends); //'wesley,fox,Rob,Barbie' ~~~ ES5通過新增`Object.create()`方法規范了原型式繼承。這個方法接收兩個參數:一個用作新對象原型的對象和(可選的)一個為新對象定義額外屬性的對象。 注:第二個參數格式與`Object.defineProperties()`方法的第二個參數格式相同:每個屬性都是通過自己的描述符定義的。以這種方式指定的任何屬性都會覆蓋原型對象上的同名屬性。 ~~~ var person = { name: 'Nicholas', friends: ['wesley','fox'] }; var anotherPerson = Object.create(person, { name:{ value: 'Greg' } }); ~~~ 在沒有必要興師動眾地創建構造函數,而只是想讓一個對象與另個對象保持類似的情況下,原型式繼承是完全可以勝任的。不過別忘了,**包含引用類型值的屬性始終都會共享相應的值,就像使用原型模式一樣。** ### 6.3.5 寄生式繼承 寄生式繼承是與原型式繼承密寫相關的一種思路:**創建一個僅用于封裝繼承過程的函數,該函數在內部以某種方式來增強對象**,最后返回對象。 ~~~ function object(o){ function F(){} F.prototype = o; return new F(); } function createAnother(original) { var clone = object(original); clone.sayHi = function(){ alert('hi'); }; return clone; } ~~~ object(o)函數不是必須的,任何能夠返回新對象的函數都適用于此模式。 這樣創建的新對象不僅具有original的所有屬性和方法,而且還有自己的sayHi()方法。在主要考慮對象而不是自定義類型和構造函數的情況下,寄生式繼承也是一種有用的模式。 ### 6.3.6 寄生組合式繼承(最有效理想) 寄生組合式繼承,即通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。 思路是:不必為了指定子類型的原型調用超類型的構造函數,我們所需要的無非就是超類型原型的一個副本而已。本質上,就是**使用寄生式繼承來繼承超類型的原型,然后再將結果指定給子類型的原型**。 ~~~ function inheritPrototype(subType,SuperType){ var prototype = object(subType.prototype); prototype.constructor = subType; subType.prototype = prototype; } function SuperType(name){ this.name = name; this.colors = ['red','blue'.'green]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,age) { //繼承屬性 SuperType.call(this,name); this.age = age; } //繼承方法 inheritPrototype(subType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); } ~~~ 寄生組合式繼承與組合繼承的區別在于,**前者不將超類型中的實例屬性繼承為子類型的原型屬性。**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看