摘要:思路是,使用原型鏈對原型屬性和方法進行繼承,借用構(gòu)造函數(shù)實現(xiàn)對實例屬性的繼承。注意使用寄生式繼承來為對象添加函數(shù),會由于不能做到函數(shù)復(fù)用而降低效率,這一點與構(gòu)造函數(shù)模式類似。無論什么情況下都會調(diào)用兩次超類型的構(gòu)造函數(shù)。
說明:
此摘要筆記系列是我最近看《JavaScript高級程序設(shè)計(第3版)》隨手所記。
里面分條列舉了一些我認為重要的、需要記下的、對我有幫助的點,是按照我看的順序來的。
摘要筆記本身沒有系統(tǒng)性,沒有全面性可言,寫在這里供有一定基礎(chǔ)的前端開發(fā)者參考交流。
里面的知識點、例子大部分來源于本書,或者延伸出來的,都經(jīng)過我的測試是對的,但是沒辦法保證100%正確,如果有人看到錯誤的地方,希望指出來,謝謝。
function Grandpa () { this.name = "Grandpa" } Grandpa.prototype.sayName = function () { console.log(this.name) } function Parent () { this.name = "Parent" } Parent.prototype = new Grandpa() Parent.prototype.sayHello = function () { console.log("hello") } var ming = new Parent() var li = new Parent() ming.sayName() // "Parent" ming.sayHello() // "hello" ming.sayHello === li.sayHello // true ming.sayName === li.sayName // true ming instanceof Parent // true ming instanceof Grandpa // true ming.constructor === Parent // false 因為在上面重新了 Parent 的原型,而且沒有重新指定 constructor ming.constructor === Grandpa // true 因為上面沒有重寫 Grandpa 的原型 ming.__proto__ === Parent.prototype // true ming.__proto__ === Grandpa.prototype // false Parent.prototype.__proto__ === Grandpa.prototype // true2. 確定原型和實例的關(guān)系
兩種方法: instanceof 操作符和 isPrototypeOf(),
如上例:
Parent.prototype.isPrototypeOf(ming) // true Grandpa.prototype.isPrototypeOf(ming) // true Object.prototype.isPrototypeOf(ming) // true3. 給原型添加方法的代碼一定放在替換原型的語句之后,否則無效 4. 原型鏈的問題
function Grandpa () { this.friends = ["ming", "li"] } function Parent () { } Parent.prototype = new Grandpa() var ming = new Parent() var li = new Parent() ming.friends.push("wang") console.log(ming.friends) // ["ming", "li", "wang"] console.log(li.friends) // ["ming", "li", "wang"] ming.friends === li.friends // true
可以解決引用類型的繼承在多個實例之間共享的問題
如:
function Grandpa () { this.friends = ["ming", "li"] } function Aunt () { Grandpa.call(this) } var ming = new Aunt() var li = new Aunt() ming.friends // ["ming", "li"] ming.friends.push("wang") li.friends // ["ming", "li"] ming.friends // ["ming", "li", "wang"]7. 借用構(gòu)造函數(shù)可以解決不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)的問題。
如:
function Grandpa (name) { this.name = name } function Parent (name, age) { Grandpa.call(this, name) this.age = age } var ming = new Parent("ming", 15) ming.age // 15 ming.name // "ming"
注意:這種情況,為了避免超類型的構(gòu)造函數(shù)(Grandpa)重寫子類型(Parnt)的屬性,應(yīng)在調(diào)用超類型構(gòu)造函數(shù)后,再添加應(yīng)該在子類型中定義的屬性
8. 借用構(gòu)造函數(shù)的問題。問題1. 函數(shù)沒有復(fù)用,占用內(nèi)存多。
問題2. 超類型原型中定義的方法,對子類型而言是不可見的,結(jié)果只能使用構(gòu)造函數(shù)模式。
有時候也叫偽經(jīng)典繼承。思路是,使用原型鏈對原型屬性和方法進行繼承,借用構(gòu)造函數(shù)實現(xiàn)對實例屬性的繼承。
如:
function Grandpa (name) { this.name = name this.friends = ["li"] } Grandpa.prototype.sayName = function () { console.log(this.name) } function Parent (name, age) { Grandpa.call(this, name) this.age = age } Parent.prototype = new Grandpa() Parent.prototype.sayAge = function () { console.log(this.age) } var ming = new Parent("ming", 12) var wang = new Parent("wang", 15) ming.name // "ming" ming.friends // ["li"] ming.friends.push("zhang") wang.friends // ["li"] ming.sayName() // "ming" ming.sayAge() // 12 ming.sayName === wang.sayName // true ming.sayAge === wang.sayAge // true ming instanceof Parent // true ming instanceof Grandpa // true10. 原型式繼承
function object (o) { function F () {} F.prototype = o return new F() }
var person = { name: "wang", friends: ["li"] } var person1 = object(person) person1.name // "wang" person1.friends // ["li"] person1.name = "zhang" person.name // "wang" var person2 = object(person) person1.friends.push("yang") person2.friends // ["li", "yang"] person2.friends === person.friends // true person1.friends === person.friends // true
這種原型式繼承,必須有一個對象作為另一個對象的基礎(chǔ)。把基礎(chǔ)對象傳入 object() 函數(shù),把得到的對象根據(jù)具體需求做修改即可。
但是別忘了所有得到的對象引用類型是共享的。
這個方法接受兩個參數(shù),一個用作新對象的原型對象,一個(可選的)為新對象定義額外屬性的對象。
在傳入一個參數(shù)的情況下, Object.create() 和 object() 的行為相同。
Object.create()的第二個參數(shù)與 Object.defineProperties() 的第二個參數(shù)格式相同:每個屬性都是通過自己的描述符來定義的。
這種方式指定的任何屬性都會覆蓋原型對象上的同名屬性。
如:
var person = { name: "wang", friends: ["li"] } var person1 = Object.create(person, { name: { value: "zhang" }, friends: { value: ["a", "b"] } }) person1.name // "zhang" person1.friends // ["a", "b"] person.friends // ["li"] // 支持 Object.create() 的瀏覽器有 IE 9+,F(xiàn)irefox 4+, Safari 5+, Opera 912+, Chrome.11. 寄生式繼承
寄生式繼承是與原型式繼承緊密相關(guān)的一種思路,和工廠模式類似。如:
function createAnother (original) { var clone = object(original) clone.sayHi = function () { console.log("hi") } return clone } var person = { name: "wang", friends: ["li"] } var person1 = createAnother(person) person1.friends // ["li"] person1.sayHi() // "hi"
新的對象person1不僅具有person的所有屬性和方法,還有自己的 sayHi() 方法。
示范的 object() 函數(shù)不是必須的,任何能夠返回新對象的函數(shù)都適用于此模式。
注意:使用寄生式繼承來為對象添加函數(shù),會由于不能做到函數(shù)復(fù)用而降低效率,這一點與構(gòu)造函數(shù)模式類似。
無論什么情況下都會調(diào)用兩次超類型的構(gòu)造函數(shù)。一次是在創(chuàng)建子類型原型的時候,一次是在子類型構(gòu)造函數(shù)內(nèi)部。
如:
function Grandpa (name) { this.name = name this.friends = ["ming"] } Grandpa.prototype.sayName = function () { console.log(this.name) } function Parent (name, age) { Grandpa.call(this, name) this.age = age } Parent.prototype = new Grandpa() // 第一次調(diào)用超類型的構(gòu)造函數(shù) Grandpa(), // 此時原型上有一個friends屬性(值是["ming"])和name屬性(值undefined,因為沒有傳參) Parent.prototype.sayHi = function () { console.log("hi") } var wang = new Parent("wang", 15) // 第二次調(diào)用超類型的構(gòu)造函數(shù) Grandpa(),在 Parent() 函數(shù)內(nèi)部調(diào)用, // 這一步的操作, Parent 的實例 wang 的屬性會覆蓋 Parent 的原型上的同名屬性 name12. 寄生組合式繼承
基本模式如下:
function inheritPrototype (subType, superType) { var prototype = object(superType.prototype) prototype.constructor = subType subType.prototype = prototype } function Grandpa (name) { this.name = name this.friends = ["ming"] } Grandpa.prototype.sayName = function () { console.log(this.name) } function Parent (name, age) { Grandpa.call(this, name) this.age = age } inheritPrototype(Parent, Grandpa) // 這里沒有調(diào)用超類型的構(gòu)造函數(shù) Grandpa() ,但是這里調(diào)用了一個函數(shù)內(nèi)部的構(gòu)造函數(shù) Parent.prototype.sayHi = function () { console.log("hi") } var li = new Parent("li", 20) // 調(diào)用超類型的構(gòu)造函數(shù) Grandpa(),在 Parent() 函數(shù)內(nèi)部調(diào)用
這種模式的好處是只調(diào)用一次 Grandpa() 構(gòu)造函數(shù),因此避免了在 Parent.prototype 上創(chuàng)建不必要的、多余的屬性。
作者講,開發(fā)人員普遍認為寄生組合式繼承是引用類型最理想的繼承范式。
繼承部分全部結(jié)束
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91656.html
摘要:說明此摘要筆記系列是我最近看高級程序設(shè)計第版隨手所記。摘要筆記本身沒有系統(tǒng)性,沒有全面性可言,寫在這里供有一定基礎(chǔ)的前端開發(fā)者參考交流。對每一項運行給定函數(shù),返回該函數(shù)會返回的項組成的數(shù)組。是的反操作是的反操作第一部分結(jié)束。 說明: 此摘要筆記系列是我最近看《JavaScript高級程序設(shè)計(第3版)》隨手所記。 里面分條列舉了一些我認為重要的、需要記下的、對我有幫助的點,是按照我看...
摘要:如果重設(shè)構(gòu)造函數(shù)的原型對象,那么,會切斷新的原型對象和任何之前已經(jīng)存在的構(gòu)造函數(shù)實例之間的聯(lián)系,它們引用的仍然是最初的原型。說明返回的對象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性沒有關(guān)系。 說明: 此摘要筆記系列是我最近看《JavaScript高級程序設(shè)計(第3版)》隨手所記。里面分條列舉了一些我認為重要的、需要記下的、對我有幫助的點,是按照我看的順序來的。摘要筆記本身沒有系統(tǒng)性,沒有全面性...
摘要:關(guān)于對象定義了全局對象。支持的瀏覽器有除了接受要序列化的對象外,還可以接受另外兩個參數(shù)。如果是數(shù)值,則表示每個級別縮進的空格數(shù),最大,超過的值自動轉(zhuǎn)換成。字符串長度超過,結(jié)果中將只出現(xiàn)前個字符。會在結(jié)果字符串中插入換行符提高可讀性。 關(guān)于JSON 1. JSON 對象 es5 定義了全局對象 JSON。支持的瀏覽器有 IE8+ 、Firefox 3.5+ 、Safari 4+、Chro...
摘要:函數(shù)表達式和閉包函數(shù)聲明的一個重要特征是函數(shù)聲明提升如遞歸遞歸函數(shù)是在一個函數(shù)通過名字調(diào)用自身的情況下構(gòu)成的。注意中已經(jīng)是塊級作用域了,所以這些東西感覺實際用途沒有那么大,但是對理解閉包對作用域鏈中的屬性的引用,這一點還是有作用的。 函數(shù)表達式和閉包 1. 函數(shù)聲明的一個重要特征是函數(shù)聲明提升 如: sayHi() function sayHi () { console.log(h...
摘要:說明此摘要筆記系列是我最近看高級程序設(shè)計第版隨手所記。其中,描述符對象的屬性必須是設(shè)置其中一個或多個值,可以修改對應(yīng)的特性值。如支持的瀏覽器,可以取得指定屬性的描述符。 說明: 此摘要筆記系列是我最近看《JavaScript高級程序設(shè)計(第3版)》隨手所記。里面分條列舉了一些我認為重要的、需要記下的、對我有幫助的點,是按照我看的順序來的。摘要筆記本身沒有系統(tǒng)性,沒有全面性可言,寫在這里...
閱讀 1785·2021-11-11 11:02
閱讀 1694·2021-09-22 15:55
閱讀 2493·2021-09-22 15:18
閱讀 3493·2019-08-29 11:26
閱讀 3752·2019-08-26 13:43
閱讀 2652·2019-08-26 13:32
閱讀 907·2019-08-26 10:55
閱讀 971·2019-08-26 10:27