日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

你真的理解JS的继承了吗?

發布時間:2025/3/21 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你真的理解JS的继承了吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

噫吁嚱,js之難,難于上青天

學習js的這幾年,在原型鏈和繼承上花了不知道多少時間,每當自以為已經吃透它的時候,總是不經意的會出現各種難以理解的幺蛾子。也許就像kyle大佬說的那樣,js的繼承真的是‘蠢弟弟’設計模式吧。

本文小綱介紹

  • es5寄生組合繼承
  • es6的class ... extends ...繼承
  • kyle大佬倡導的行為委托

閱讀本文之前先約定,本文中稱 __proto__ 為 內置原型,稱 prototype 為 原型對象,構造函數 SubType 和 SuperType 分別稱為子類和父類。

請先看下圖,如果各位覺得soeasy,請直接 插隊這里 。

es5寄生組合繼承

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 = Object.create(SuperType.prototype, {constructor: {value: SubType,enumerable: false,writable: true,configurable: true} }) SubType.prototype.sayAge = function(){alert(this.age); }; let instance = new SubType('gim', '17'); instance.sayName(); // 'gim' instance.sayAge(); // '17' 復制代碼
  • 首先,這段代碼聲明了父類 SuperType
  • 其次,聲明了父類的原型對象方法 sayName。
  • 再次,聲明了子類 SubType,并在未來將要新創建的 SubType 實例環境上調用父類 SuperType.call,以獲取父類中的 name 和 colors 屬性。
  • 再次,用 Object.create() 方法把子類的原型對象上的內置對象 __proto__ 指向了父類的原型對象,并把子類構造函數重新賦值為子類。
  • 然后,給子類的原型對象上添加方法 sayAge。
  • 最后初始化實例對象instance。(調用new SubType('gim', '17')的時候會生成一個__proto__指向SubType.prototype的空對象,然后把this指向這個空對象。在添加完name、colors、age屬性之后,返回這個‘空對象’,也就是說instance最終就是這個‘空對象’。)
  • 此時,代碼中生成的原型鏈關系如下圖所示(下面三張圖擼了一下午,喜歡的幫忙點個贊謝謝):

    • 子類的原型對象的 __proto__ 指向父類的原型對象。 圖中有兩種顏色的帶箭頭的線,紅色的線是我們生成的實例的原型鏈,是我們之所以能調用到 instance.sayName() 和 instance.sayAge() 的根本所在。當調用instance.sayName()的時候,js引擎會先查找instance對象中的自有屬性。未找到sayName屬性,則繼續沿原型鏈查找,此時instance通過內置原型__proto__鏈到了SubType.prototype對象上。但在SubType.prototype上也未找到sayName屬性,繼續沿原型鏈查找,此時SubType.prototype的__proto__鏈到了SuperType.prototype對象上。在對象上找到了sayName屬性,于是查找結束,開始調用。因此調用instance.sayName()相當于調用了instance.__proto__.__proto__.sayName(),只不過前者中sayName函數內this指向instance實例對象,而后者sayName函數內的this指向了SuperType.prototype(instance.__proto__.__proto__ === SuperType.prototype)對象。

    • 在 es5 的實現中,子類的 __proto__ 直接指向的是 Function.prototype。 黑色的帶箭頭的線則是 es5 繼承中產生的‘副作用’,使得所有的函數的 __proto__ 指向了 Function.prototype,并最終指向 Object.prototype,從而使得我們聲明的函數可以直接調用 toString(定義在Function.prototype上)、hasOwnProperty(定義在Object.prototype上) 等方法,如:SubType.toString()、SubType.hasOwnProperty()等。

      下面看看es6中有哪些不同吧。

    es6的class ... extends ...

    class SuperType {constructor(name) {this.name = namethis.colors = ["red", "blue", "green"];}sayName() {alert(this.name)} } class SubType extends SuperType {constructor(name, age){super(name)this.age = age}sayAge() {alert(this.age)} } let instance = new SubType('gim', '17'); instance.sayName(); // 'gim' instance.sayAge(); // '17' 復制代碼

    可以明顯的發現這段代碼比之前的更加簡短和美觀。es6 class 實現繼承的核心在于使用關鍵字 extends 表明繼承自哪個父類,并且在子類構造函數中必須調用 super 關鍵字,super(name)相當于es5繼承實現中的 SuperType.call(this, name)。

    雖然結果可能如你所料的實現了原型鏈繼承,但是這里還是有個需要注意的點值得一說。

    如圖,es6中的 class 繼承存在兩條繼承鏈:

  • 子類prototype屬性的__proto__屬性,表示方法的繼承,總是指向父類的prototype屬性。 這點倒和經典繼承是一致的。 如紅線所示,子類SubType的prototype屬性的__proto__指向父類SuperType的prototype屬性。 相當于調用Object.setPrototypeOf(SubType.prototype, SuperType.prototype); 因為和經典繼承相同,這里不再累述。

  • 子類的__proto__屬性,表示構造函數的繼承,總是指向父類。 這是個值得注意的點,和es5中的繼承不同,如藍線所示,子類SubType的__proto__指向父類SuperType。相當于調用了Object.setPrototypeOf(SubType, SuperType); es5繼承中子類和父類的內置原型直接指向的都是Function.prototype,所以說Function是所有函數的爸爸。而在es6class...extends...實現的繼承中,子類的內置原型直接指向的是父類。 之所以注意到這點,是因為看 kyle 大佬的《你不知道的javascript 下》的時候,看到了class MyArray extends Array{}和var arr = MyArray.of(3)這兩行代碼,很不理解為什么MyArray上面為什么能調到of方法。因為按照es5中繼承的經驗,MyArray.__proto__應該指向了Function.prototype,而后者并沒有of方法。當時感覺世界觀都崩塌了,為什么我以前的認知失效了?第二天重翻阮一峰老師的《ECMAScript6入門》才發現原來class實現的繼承是不同的。

  • 知道了這點,就可以根據需求靈活運用Array類構造自己想要的類了:

    class MyArray extends Array {[Symbol.toPrimitive](hint){if(hint === 'default' || hint === 'number'){ return this.reduce((prev,curr)=> prev+curr, 0)}else{return this.toString()}} } let arr = MyArray.of(2,3,4); arr+''; // '9' 復制代碼

    元屬性Symbol.toPrimitive定義了MyArray的實例發生強制類型轉換的時候應該執行的方法,hint的值可能是default/number/string中的一種。現在,實例arr能夠在發生加減乘除的強制類型轉換的時候,數組內的每項會自動執行加性運算。

    以上就是js實現繼承的兩種模式,可以發現class繼承和es5寄生組合繼承有相似之處,也有不同的地方。雖然class繼承存在一些問題(如暫不支持靜態屬性等),但是子類的內置原型指向父類這點是個不錯的改變,這樣我們就可以利用原生構造函數(Array等)構建自己想要的類了。

    kyle大佬提到的行為委托

    在讀《你不知道的javascript 上》的時候,感觸頗多。這本書真的是本良心書籍,讓我學會了LHS/RHS,讀懂了閉包,了解了詞法作用域,徹底理解了this指向,基本懂了js的原型鏈繼承。所以當時就忍不住又從頭讀了一遍。如果說諸多感受中最大的感受是啥,那一定是行為委托了。我第一次見過有大佬能夠如此強悍(至少沒見過國內的大佬這么牛叉的),強悍到直接號召讀者抵制js的繼承模式(無論寄生組合繼承還是class繼承),并且提倡使用行為委托模式實現對象的關聯。我真的被折服了,要知道class可是w3c委員會制定出的標準,并且已經廣泛的應用到了業界中。關鍵的關鍵是,我確實認為行為委托確實更加清晰簡單(如有異議請指教)。

    let SuperType = {initSuper(name) {this.name = namethis.color = [1,2,3]},sayName() {alert(this.name)} } let SubType = {initSub(age) {this.age = age},sayAge() {alert(this.age)} } Object.setPrototypeOf(SubType,SuperType) SubType.initSub('17') SubType.initSuper('gim') SubType.sayAge() // 'gim' SubType.sayName() // '17' 復制代碼

    這就是模仿上面js繼承的兩個例子,利用行為委托實現的對象關聯。行為委托的實現非常超級極其的簡單,就是把父對象關聯到子對象的內置原型上,這樣就可以在子對象上直接調用父對象上的方法。行為委托生成的原型鏈沒有class繼承生成的原型鏈的復雜關系,一目了然。當然class有其存在的道理,但是在些許場景下,應該是行為委托更加合適吧。希望safari盡快實現Object.setPrototypeOf()方法,太out了連ie都支持了。

    小子愚鈍,如果行為委托完全能夠實現實現class繼承的功能,而且更加簡單和清晰,我們開發的過程中為什么不愉快的嘗試用一下呢?

    總結

    以上是生活随笔為你收集整理的你真的理解JS的继承了吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 一女双乳被两男吸视频 | 国产精品久久久久久久久久直播 | 美女av一区二区 | 中文字幕亚洲一区二区三区 | 天堂av观看 | 天堂av在线网 | 国产精品亚洲专区无码牛牛 | 中文在线天堂网 | 国产在线观看无码免费视频 | 欧美日韩亚洲在线 | 久久老熟女一区二区三区 | 狠狠插综合| 亚洲成av人片一区二区 | 一本加勒比北条麻妃 | 中文字幕狠狠 | 亚洲最大激情网 | 91午夜影院 | 一区二区手机在线 | 亚洲免费福利视频 | 2020国产在线 | 蜜臀99久久精品久久久久久软件 | 欧美视频一| 少妇人妻偷人精品视频蜜桃 | 人妖一级片 | 国产一区免费视频 | 中文字幕精品一区 | 6080午夜| 在线一区av | 日韩精品成人在线 | 99综合视频| 成人黄色激情网 | 黄色三级小视频 | 日韩免费观看一区二区 | 4438国产精品一区二区 | 日本妇女毛茸茸 | 色啪综合 | 成人午夜免费观看 | 激情91视频 | 久久成人激情 | 777777av| 丁香五香天堂网 | 亚洲色图第1页 | 成a人片亚洲日本久久 | 白白色视频在线 | 亚洲精品久久久久久久久久久久久 | 国产精品腿扒开做爽爽爽挤奶网站 | 亚洲精品一区中文字幕乱码 | 色婷婷狠狠爱 | 婷婷亚洲视频 | 一区二区视频在线 | 免费人成又黄又爽又色 | 美女乱淫 | 伊人久久大香线蕉综合75 | 成人在线播放视频 | 婷婷精品 | 欧美freesex黑人又粗又大 | 国产精品国产一区 | 亚洲精品国产日韩 | 日本www免费 | 国产激情在线播放 | 欧美一区精品 | 精品国产91久久久久久 | 91午夜理伦私人影院 | 国产精品综合一区二区 | jizz色| 黄色片小视频 | 国产精品免费大片 | 天天搞天天 | 超碰人人国产 | 超碰在线免费播放 | 97狠狠干| 黄色资源网站 | 国产精品一区二区三区四区在线观看 | 美日韩一二三区 | 最新色站| 久操视频免费 | jizzzxxxx | 午夜黄色av | 一区二区三区四区视频 | 日韩精品一区二区三区视频在线观看 | 国产资源在线播放 | 国产色| 亚洲综合图| 涩五月婷婷 | 菲律宾黄色片 | 黄色刺激视频 | 欧美乱强伦 | 人妻少妇精品一区二区 | 91久色视频 | 91精品国产综合久久久蜜臀九色 | 中文字幕在线视频一区二区三区 | 深夜福利91 | 人妻无码一区二区三区四区 | 久久久久亚洲国产 | 色呦呦在线视频 | www.成人精品 | 久久久国产精品黄毛片 | 久久婷婷综合色 | 少妇高潮毛片色欲ava片 |