<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
前文已提過:在 class 出現之前,JavaScript 實現繼承是件麻煩事,建構函式繼承有加上原型上的函數不能複用的問題;原型鏈繼承又存在參照值屬性的修改不獨立的問題;組合繼承又存在兩次呼叫建構函式的問題,寄生組合繼承,寫起來又太麻煩了,總之,在 class 出現前,JavaScipt 實現繼承真是件麻煩事兒。
然而,class 的出現真的改變這一現狀了嗎?
不如往下看。
與函數型別相似,定義類也有兩種主要方式:類宣告和類表示式。
// 類宣告 class Person {}
// 類表示式 const Animal = class {};
不過,與函數定義不同的是,雖然函數宣告可以提升,但類定義不能。
與函數建構函式一樣,多數程式設計風格都建議類名的首字母要大寫,以區別於通過它建立的範例。
類可以包含:
這些項都是可選的
class Person { constructor(name) { this.name = name console.log('person ctor'); } } let p1 = new Person("p1")
constructor 會告訴直譯器 在使用 new 操作符建立類的新範例時,應該呼叫這個函數。
等同於
function Person(name){ this.name = name console.log('person ctor') } let p1 = new Person("p1")
類建構函式與建構函式的主要區別是,這樣寫會報錯:
class Animal {} let a = Animal(); // TypeError: class constructor Animal cannot be invoked without 'new'
所以,new 操作符是強制要寫的;
使用 new 時,原理與 new 一個物件也是一樣的,因為太重要了,再強調一遍:
(1) 在記憶體中建立一個新物件。
(2) 這個新物件內部的[[Prototype]]指標被賦值為建構函式的 prototype 屬性。
(3) 建構函式內部的 this 被賦值為這個新物件(即 this 指向新物件)。
(4) 執行建構函式內部的程式碼(給新物件新增屬性)。
(5) 如果建構函式返回非空物件,則返回該物件;否則,返回剛建立的新物件。
從各方面來看,ECMAScript 類就是一種特殊函數。
我們可以用 typeof 列印試試:
class Person {} console.log(typeof Person); // function
也可以用 instanceof 檢查它的原型鏈
class Person {} let p = new Person() console.log(p instanceof Person); // true
通過 class 構造的每個範例都對應一個唯一的成員物件,這意味著所有成員都不會在原型上共用;
class Person { constructor() { this.name = new String('Jack'); this.sayName = () => console.log(this.name); } } let p1 = new Person(); let p2 = new Person(); console.log(p1.name === p2.name) // false console.log(p1.sayName === p2.sayName) // false
如果想要共用,就改寫成方法,寫在 constructor 外面:
class Person { constructor() { this.name = new String('Jack'); } sayName(){ console.log(this.name); } } let p1 = new Person(); let p2 = new Person(); console.log(p1.sayName === p2.sayName) // true
我們可以在方法前面加 static 關鍵字,實現:靜態類成員。我們不能在類的範例上呼叫靜態方法,只能通過類本身呼叫。不做贅述。
ECMAScript 6 新增特性中最出色的一個就是原生支援了類繼承機制。雖然類繼承使用的是新語法,但背後依舊使用的是原型鏈。
讓我們再回顧建構函式繼承和原型鏈繼承 2 個經典的問題:
① 建構函式繼承的問題:建構函式外在原型上定義方法,不能重用
function SuperType(){} SuperType.prototype.sayName = ()=>{console.log("bob")} function SubType(){ SuperType.call(this) // 建構函式繼承 } let p1 = new SubType() console.log(p1.sayName()) // Uncaught TypeError: p1.sayName is not a function
而原型鏈繼承可以解決這一點:
function SuperType(){} SuperType.prototype.sayName = ()=>{console.log("bob")} function SubType(){} SubType.prototype = new SuperType() // 原型鏈繼承 let p1 = new SubType() console.log(p1.sayName()) // bob
② 原型鏈繼承的問題:原型中包含的參照值會在所有範例間共用。
function SuperType(){ this.name = ["bob","tom"]; } function SubType(){} SubType.prototype = new SuperType() // 原型鏈繼承 let p1 = new SubType() p1.name.push("jerry") let p2 = new SubType() console.log(p2.name) // ['bob', 'tom', 'jerry']
而建構函式繼承可以解決這一點:
function SuperType(){ this.name = ["bob","tom"]; } function SubType(){ SuperType.call(this) // 建構函式繼承 } let p1 = new SubType() p1.name.push("jerry") let p2 = new SubType() console.log(p2.name) // ['bob', 'tom']
class 繼承有這兩個問題嗎??
程式碼一試便知:
class SuperType{} SuperType.prototype.sayName = ()=>{console.log("bob")} class SubType extends SuperType{ } let p1 = new SubType() p1.sayName() // bob
問題①,沒有問題,在建構函式外寫的原型繼承,公共方法還是能存取的!!
class SuperType{ constructor(){ this.name=["bob","tom"] } } class SubType extends SuperType{ } let p1 = new SubType() let p2 = new SubType() p1.name.push("Jerry") console.log(p2.name) // ['bob', 'tom']
問題②,沒有問題,在 constructor 的參照值屬性,修改不會產生干涉!!
class 繼承完美的解決了建構函式繼承的問題,和原型鏈繼承的問題,寫起來也沒有組合繼承、寄生繼承那麼麻煩,如果非得用 JS 模擬物件導向程式設計,class 必不可少!!
其實寫 Class C 和 C.prototype 一起寫是很危險的:明明都在操作物件導向的類了,還要操作原型鏈。類操作和原型操作是兩種不同的設計思路,有興趣可見本瓜一年前的一篇文章:“類”設計模式和“原型”設計模式——“複製”和“委託”的差異
以上就是JS高階程式設計之class繼承重點詳解的詳細內容,更多關於JS高階程式設計class繼承的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45