摘要:實(shí)現(xiàn)繼承定義一個(gè)父類定義一個(gè)動(dòng)物類屬性實(shí)例方法正在睡覺(jué)原型方法正在吃原型鏈繼承核心將父類的實(shí)例作為子類的原型特點(diǎn)非常純粹的繼承關(guān)系,實(shí)例是子類的實(shí)例,也是父類的實(shí)例父類新增的原型方法屬性,子類都能訪問(wèn)到簡(jiǎn)單,易于實(shí)現(xiàn)缺點(diǎn)要想為子類新增屬性和
JS實(shí)現(xiàn)繼承 JavaScript 定義一個(gè)父類:
// 定義一個(gè)動(dòng)物類 function Animal (name) { // 屬性 this.name = name || ‘Animal’; // 實(shí)例方法 this.sleep = function(){ console.log(this.name + ‘正在睡覺(jué)!’); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + ‘正在吃:’ + food); };1.原型鏈繼承
核心:將父類的實(shí)例作為子類的原型
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = ‘cat’; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat(‘fish’)); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
特點(diǎn):
非常純粹的繼承關(guān)系,實(shí)例是子類的實(shí)例,也是父類的實(shí)例
父類新增的原型方法、屬性,子類都能訪問(wèn)到
簡(jiǎn)單,易于實(shí)現(xiàn)
缺點(diǎn):
要想為子類新增屬性和方法,必須要在new Animal()這樣的語(yǔ)句之后執(zhí)行(可以在cat構(gòu)造函數(shù)中,為Cat實(shí)例增加實(shí)例屬性)
無(wú)法實(shí)現(xiàn)多繼承
來(lái)自原型對(duì)象的引用屬性被所有實(shí)例共享
創(chuàng)建子類實(shí)例時(shí),無(wú)法向父類構(gòu)造函數(shù)傳參
下面代碼解釋缺點(diǎn)3(注意是引用屬性):
function Super(){ this.val = 1; this.arr = [1]; } function Sub(){ // ... } Sub.prototype = new Super(); // 核心 var sub1 = new Sub(); var sub2 = new Sub(); sub1.val = 2; sub1.arr.push(2); alert(sub1.val); // 2 alert(sub2.val); // 1 alert(sub1.arr); // 1, 2 alert(sub2.arr); // 1, 22.構(gòu)造繼承
核心:使用父類的構(gòu)建函數(shù)來(lái)增強(qiáng)子類實(shí)例,等于復(fù)制父類的實(shí)例屬性給子類(沒(méi)用到原型),除了call方法,也可以用apply()
function Cat(name){ Animal.call(this); this.name = name || ‘Tom’; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
特點(diǎn):
解決了1中,子類實(shí)例共享父類引用屬性的問(wèn)題
創(chuàng)建子類實(shí)例時(shí),可以向父類傳遞參數(shù)
可以實(shí)現(xiàn)多繼承(call多個(gè)父類對(duì)象)
缺點(diǎn):
實(shí)例并不是父類的實(shí)例,只是子類的實(shí)例
只能繼承父類的實(shí)例屬性和方法,不能繼承原型屬性和方法
無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類都有父類的實(shí)例函數(shù)的副本,影響性能
3.實(shí)例繼承核心:為父類實(shí)例添加新特性,作為子類實(shí)例返回
function Cat(name){ var instance = new Animal(); instance.name = name || ‘Tom’; return instance; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // false
特點(diǎn):
不限制調(diào)用方式,不管是new 子類()還是子類(),返回的對(duì)象都具有相同的效果
缺點(diǎn):
實(shí)例是父類的實(shí)例,不是子類的實(shí)例
不支持多繼承
4. 拷貝繼承核心:使用for...in將父類實(shí)例中的方法賦給子類實(shí)例
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || ‘Tom’; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
特點(diǎn):
支持多繼承
缺點(diǎn):
效率較低,內(nèi)存占用高(因?yàn)橐截惛割惖膶傩裕?/p>
無(wú)法獲取父類不可枚舉的方法(for in無(wú)法訪問(wèn)不可枚舉的方法)
5.組合繼承核心:通過(guò)調(diào)用父類構(gòu)造,繼承父類的屬性并保留傳參的優(yōu)點(diǎn),然后通過(guò)將父類實(shí)例作為子類原型,實(shí)現(xiàn)函數(shù)復(fù)用
function Cat(name){ Animal.call(this); this.name = name || ‘Tom’; } Cat.prototype = new Animal(); //組合繼承需要修復(fù)構(gòu)造函數(shù)的指向 Cat.prototype.constructor=Cat; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true
特點(diǎn):
彌補(bǔ)了方式2的缺陷,可以繼承實(shí)例屬性、方法,也可以繼承原型屬性、方法
既是子類的實(shí)例,也是父類的實(shí)例
不存在引用屬性的共享問(wèn)題
可傳參
函數(shù)可復(fù)用
缺點(diǎn):
調(diào)用了兩次父類構(gòu)造函數(shù),生成了兩份實(shí)例(子類實(shí)例將子類原型上的那份屏蔽了)
6.寄生組合繼承核心:通過(guò)寄生方式,砍掉父類的實(shí)例屬性,這樣,在調(diào)用兩次父類的構(gòu)造的時(shí)候,就不會(huì)初始化兩次實(shí)例方法/屬性,避免的組合繼承的缺點(diǎn)
function Cat(name){ Animal.call(this); this.name = name || ‘Tom’; } (function(){ // 創(chuàng)建一個(gè)沒(méi)有實(shí)例方法的類 var Super = function(){}; Super.prototype = Animal.prototype; //將實(shí)例作為子類的原型 Cat.prototype = new Super(); //寄生組合繼承需要修復(fù)構(gòu)造函數(shù)的指向 Cat.prototype.constructor=Cat; })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true
特點(diǎn):
堪稱完美
缺點(diǎn):
實(shí)現(xiàn)較為復(fù)雜
補(bǔ)充:es6的class實(shí)現(xiàn)繼承
class Animal { //構(gòu)造函數(shù) constructor(props) { this.name = props.name || "未知"; } eat() { alert(this.name + "在吃東西..."); } } //class繼承 class Bird extends Animal { //構(gòu)造函數(shù) constructor(props) { //調(diào)用實(shí)現(xiàn)父類的構(gòu)造函數(shù) super(props); this.name = props.name || "未知"; } fly() { alert(this.name + "在飛..."); } } var myBird = new Bird({ name: "鸚鵡" }) myBird.eat() // 鸚鵡在吃東西... myBird.fly() // 鸚鵡在飛...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101164.html
摘要:是完全的面向?qū)ο笳Z(yǔ)言,它們通過(guò)類的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街?,?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來(lái)的。 JavaScript 函數(shù)式腳本語(yǔ)言特性以及其看似隨意的編寫(xiě)風(fēng)格,導(dǎo)致長(zhǎng)期以來(lái)人們對(duì)這一門(mén)語(yǔ)言的誤解,即認(rèn)為 JavaScript 不是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從?duì)語(yǔ)言感悟的角度闡述為什...
摘要:可以通過(guò)構(gòu)造函數(shù)和原型的方式模擬實(shí)現(xiàn)類的功能。原型式繼承與類式繼承類式繼承是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型的構(gòu)造函數(shù)。寄生式繼承這種繼承方式是把原型式工廠模式結(jié)合起來(lái),目的是為了封裝創(chuàng)建的過(guò)程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對(duì)象間的繼承) 類式繼承(構(gòu)造函數(shù)間的繼承) 由于js不像java那樣是真正面向?qū)ο蟮恼Z(yǔ)言,js是基于對(duì)象的,它沒(méi)有類的概念。...
摘要:一些面向?qū)ο笳Z(yǔ)言中支持多繼承,在也能實(shí)現(xiàn)多繼承,但是有一些局限,因?yàn)樵谥欣^承是依賴原型鏈實(shí)現(xiàn)的,只有一條原型鏈,所以理論上是不能繼承多個(gè)父類的。從第一個(gè)參數(shù)起為被繼承的對(duì)象獲取參數(shù)長(zhǎng)度緩存參數(shù)對(duì)象緩存當(dāng)前對(duì)象遍歷被繼承對(duì)象中的屬性 一些面向?qū)ο笳Z(yǔ)言中支持多繼承,在JavaScript也能實(shí)現(xiàn)多繼承,但是有一些局限,因?yàn)樵贘avaScript中繼承是依賴原型prototype鏈實(shí)現(xiàn)的,只...
摘要:的繼承方式屬于原型式繼承,非常靈活。當(dāng)使用關(guān)鍵字執(zhí)行類的構(gòu)造函數(shù)時(shí),系統(tǒng)首先創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象會(huì)繼承自構(gòu)造函數(shù)的原型對(duì)象新對(duì)象的原型就是構(gòu)造函數(shù)的屬性。也就是說(shuō),構(gòu)造函數(shù)用來(lái)對(duì)生成的新對(duì)象進(jìn)行一些處理,使這個(gè)新對(duì)象具有某些特定的屬性。 繼承這個(gè)東西在Javascript中尤其復(fù)雜,我掌握得也不好,找工作面試的時(shí)候在這個(gè)問(wèn)題上栽過(guò)跟頭。Javascript的繼承方式屬于原型式繼承,...
摘要:雖然,也是面向疾苦的語(yǔ)言,但是,它和靜態(tài)類型語(yǔ)言的面向接口編程不一而足。對(duì)象對(duì)他自己的行為負(fù)責(zé),其他對(duì)象不關(guān)心它的內(nèi)部實(shí)現(xiàn)。 ‘工欲善其事,必先利其器’,在深入學(xué)習(xí)JavaScript之前,我認(rèn)為我們很有必要了解以下,JavaScript這門(mén)面向?qū)ο蟮膭?dòng)態(tài)語(yǔ)言到底是一門(mén)什么樣的語(yǔ)言。 JavaScript vs 其他面向?qū)ο笳Z(yǔ)言 它沒(méi)有使用像Java等傳統(tǒng)的面向?qū)ο笳Z(yǔ)言的類式繼承,而...
摘要:構(gòu)造函數(shù)所以,就有了畸形的繼承方式原型鏈繼承三原型鏈繼承改變構(gòu)造函數(shù)的原型對(duì)象繼承了屬性以上例子中,暴露出原型鏈繼承的兩個(gè)問(wèn)題包含引用類型數(shù)據(jù)的原型屬性,會(huì)被所有實(shí)例共享,基本數(shù)據(jù)類型則不會(huì)。 前言 眾所周知,JavaScript 中,沒(méi)有 JAVA 等主流語(yǔ)言類的概念,更沒(méi)有父子類繼承的概念,而是通過(guò)原型對(duì)象和原型鏈的方式實(shí)現(xiàn)繼承。 于是,我們這一篇講一講 JS 中的繼承(委托)。 ...
閱讀 1356·2023-04-25 23:47
閱讀 931·2021-11-23 09:51
閱讀 4486·2021-09-26 10:17
閱讀 3735·2021-09-10 11:19
閱讀 3270·2021-09-06 15:10
閱讀 3558·2019-08-30 12:49
閱讀 2439·2019-08-29 13:20
閱讀 1745·2019-08-28 18:14