<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
JS和Java中雖然都有物件的概念,但這兩種物件卻大有不同。Java的物件是基於類建立的,JS的物件卻是基於一個特殊的物件——原型物件——建立的,之前看到一個蓋房子的比喻,在Java中蓋房子是先畫好圖紙再蓋房子,JS中蓋房子卻是先蓋一個樣板房再蓋其他房子,覺得也挺貼切。
所以JS中的繼承和Java中的繼承就大有不同了,是基於原型物件的,如果兩個物件形成繼承關係,那必然是其中一個物件的原型鏈上存在一個指標指向另一個物件。即使JS中的兩個類宣告了繼承關係,也是表現在原型物件上。比如:
class A { say() { console.log('say: hello!'); } } class B extends A { constructor() { super(); } } console.log(A.prototype); // {constructor: ƒ, say: ƒ} console.log(B.__proto__); // class A {} console.log(B.prototype); // A {constructor: ƒ}
首先,類是JS中函數的語法糖,並且在JS中函數本身也是物件,也就是說A和B是兩個物件,所以extends操作使得B自身的原型屬性__proto__
指向了A,相當於const B = Object.create(A);
。
其次,類的繼承關係也影響其生成的範例,眾所周知,函數本身存在一個特殊的物件屬性:prototype,函數經過構造呼叫產生的範例的原型屬性__proto__
是指向這個物件的,而extends操作修改了B的prototype物件,所以B範例上的原型屬性__proto__
也就被修改了,通過B範例的原型屬性__proto__
能找到A的prototype,即在B範例的原型鏈上能找到A的prototype。
const b = new B(); console.log(b.__proto__); // A {constructor: ƒ} 即B.prototype console.log(b.__proto__.__proto__); // {constructor: ƒ, say: ƒ} 即A.prototype
在JS中使用字面量定義的物件時,其預設的原型屬性__proto__
指向Object的prototype物件,相當於預設繼承自Object,所以字面量物件可以呼叫Object
的實體方法。
可以使用isPrototypeOf
來判斷一個物件是否在另一個物件的原型鏈上。
由上述可知,JS中的繼承關係與原型物件密切相關,為了達到繼承的關聯關係(共用某些屬性和方法),就要從原型物件著手:
1.使用Object.create的方式建立物件,使兩個物件直接產生繼承關係
const o1 = { name: 'o1', age: 18, walk() { console.log('walking...') } }; const o2 = Object.create(o1); console.log(o2.__proto__); // {name: 'o1', age: 18} console.log(o2.walk()); // walking... console.log(o1.isPrototypeOf(o2)); // true
2.使用new操作建立物件,使產生的範例和類(或函數)的原型物件產生繼承關係
const b = new B(); console.log(B.prototype); // A {constructor: ƒ} console.log(b.__proto__); // A {constructor: ƒ} 即B.prototype console.log(B.prototype.isPrototypeOf(b)); // true
3.使用extends關鍵字使類形成繼承關係,擴充套件類範例的原型鏈
class A { say() { console.log('say: hello!'); } } class B extends A { constructor() { super(); } } console.log(A.prototype); // {constructor: ƒ, say: ƒ} const b = new B(); console.log(b.__proto__.__proto__); // {constructor: ƒ, say: ƒ} 即A.prototype console.log(A.isPrototypeOf(B)); // true console.log(A.isPrototypeOf(b)); // false console.log(A.prototype.isPrototypeOf(b)); // true
4.修改函數的prototype屬性使函數形成繼承關係,擴充套件函數範例的原型鏈
function C() { this.name = 'c'; this.operation = function() { return 'printing...'}; } function D() {} D.prototype = new C(); const d = new D(); console.log(d.__proto__.__proto__ === C.prototype); // true console.log(C.prototype.isPrototypeOf(d)); // true console.log(D.prototype.isPrototypeOf(d)); // true
這裡存在一個問題,就是子類範例化時無法向父類別的建構函式傳參
5.盜用父類別建構函式
在函數內部通過call或apply呼叫父類別函數(非構造呼叫),可繼承父類別範例自身(非原型物件)的屬性和方法(相當於把子類範例(即this)傳遞進父類別函數,對這個this做了一遍操作),雖然可在初始化時傳遞引數給父類別,但無法形成原型鏈
function E() { C.call(this); this.do = function () { return 'do homework'; } } const e = new E(); console.log(E.prototype.isPrototypeOf(e)); // true console.log(C.prototype.isPrototypeOf(e)); // false console.log(e); // E {name: 'c', operation: ƒ, do: ƒ} console.log(e.do()); // do homework
子類產生的範例無法對父類別及其原型物件應用instanceof和isPrototypeOf方法。
此時如果父類別想共用方法給子類,必須把方法直接在定義在函數內部,繫結到範例上,而無法通過父類別的prototype物件共用。
6.結合4和5,使得子類範例可繼承父類別原型物件的屬性和方法,且能形成原型鏈
function E() { C.call(this); this.do = function () { return 'do homework'; } } E.prototype = new C(); const e = new E(); console.log(E.prototype.isPrototypeOf(e)); // true console.log(C.prototype.isPrototypeOf(e)); // true console.log(e); // E {name: 'c', operation: ƒ, do: ƒ} console.log(e.do()); // do homework
7.用Object.create()替換new父類別範例來重寫子類的原型物件
function inheritatePrototype(subT, superT) { let proto = Object.create(superT.prototype); proto.constructor = subT; subT.prototype = proto; } inheritatePrototype(E, C);
可以捨去new中不需要的操作
8.通過工廠方式共用屬性和方式
類似工廠函數,但不是用裸的Object,以某種方式取得物件(如new等返回新物件的函數),對此物件加屬性或方法以增強功能,並返回物件。
function createAnother(original) { let clone = Object.create(original); clone.xx = xxx; return clone; }
適合主要關注物件,而不在乎型別和建構函式的場景
存在的問題: 必須在建構函式中定義方法(屬於範例非原型物件的方法),函數不能重用
到此這篇關於JavaScript中常見的繼承方式總結的文章就介紹到這了,更多相關JavaScript繼承方式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援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