摘要:實現繼承定義一個父類定義一個動物類屬性實例方法正在睡覺原型方法正在吃原型鏈繼承核心將父類的實例作為子類的原型特點非常純粹的繼承關系,實例是子類的實例,也是父類的實例父類新增的原型方法屬性,子類都能訪問到簡單,易于實現缺點要想為子類新增屬性和
JS實現繼承 JavaScript 定義一個父類:
// 定義一個動物類 function Animal (name) { // 屬性 this.name = name || ‘Animal’; // 實例方法 this.sleep = function(){ console.log(this.name + ‘正在睡覺!’); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + ‘正在吃:’ + food); };1.原型鏈繼承
核心:將父類的實例作為子類的原型
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
特點:
非常純粹的繼承關系,實例是子類的實例,也是父類的實例
父類新增的原型方法、屬性,子類都能訪問到
簡單,易于實現
缺點:
要想為子類新增屬性和方法,必須要在new Animal()這樣的語句之后執行(可以在cat構造函數中,為Cat實例增加實例屬性)
無法實現多繼承
來自原型對象的引用屬性被所有實例共享
創建子類實例時,無法向父類構造函數傳參
下面代碼解釋缺點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.構造繼承
核心:使用父類的構建函數來增強子類實例,等于復制父類的實例屬性給子類(沒用到原型),除了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
特點:
解決了1中,子類實例共享父類引用屬性的問題
創建子類實例時,可以向父類傳遞參數
可以實現多繼承(call多個父類對象)
缺點:
實例并不是父類的實例,只是子類的實例
只能繼承父類的實例屬性和方法,不能繼承原型屬性和方法
無法實現函數復用,每個子類都有父類的實例函數的副本,影響性能
3.實例繼承核心:為父類實例添加新特性,作為子類實例返回
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
特點:
不限制調用方式,不管是new 子類()還是子類(),返回的對象都具有相同的效果
缺點:
實例是父類的實例,不是子類的實例
不支持多繼承
4. 拷貝繼承核心:使用for...in將父類實例中的方法賦給子類實例
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
特點:
支持多繼承
缺點:
效率較低,內存占用高(因為要拷貝父類的屬性)
無法獲取父類不可枚舉的方法(for in無法訪問不可枚舉的方法)
5.組合繼承核心:通過調用父類構造,繼承父類的屬性并保留傳參的優點,然后通過將父類實例作為子類原型,實現函數復用
function Cat(name){ Animal.call(this); this.name = name || ‘Tom’; } Cat.prototype = new Animal(); //組合繼承需要修復構造函數的指向 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
特點:
彌補了方式2的缺陷,可以繼承實例屬性、方法,也可以繼承原型屬性、方法
既是子類的實例,也是父類的實例
不存在引用屬性的共享問題
可傳參
函數可復用
缺點:
調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)
6.寄生組合繼承核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點
function Cat(name){ Animal.call(this); this.name = name || ‘Tom’; } (function(){ // 創建一個沒有實例方法的類 var Super = function(){}; Super.prototype = Animal.prototype; //將實例作為子類的原型 Cat.prototype = new Super(); //寄生組合繼承需要修復構造函數的指向 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
特點:
堪稱完美
缺點:
實現較為復雜
補充:es6的class實現繼承
class Animal { //構造函數 constructor(props) { this.name = props.name || "未知"; } eat() { alert(this.name + "在吃東西..."); } } //class繼承 class Bird extends Animal { //構造函數 constructor(props) { //調用實現父類的構造函數 super(props); this.name = props.name || "未知"; } fly() { alert(this.name + "在飛..."); } } var myBird = new Bird({ name: "鸚鵡" }) myBird.eat() // 鸚鵡在吃東西... myBird.fly() // 鸚鵡在飛...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101164.html
摘要:是完全的面向對象語言,它們通過類的形式組織函數和變量,使之不能脫離對象存在。而在基于原型的面向對象方式中,對象則是依靠構造器利用原型構造出來的。 JavaScript 函數式腳本語言特性以及其看似隨意的編寫風格,導致長期以來人們對這一門語言的誤解,即認為 JavaScript 不是一門面向對象的語言,或者只是部分具備一些面向對象的特征。本文將回歸面向對象本意,從對語言感悟的角度闡述為什...
摘要:可以通過構造函數和原型的方式模擬實現類的功能。原型式繼承與類式繼承類式繼承是在子類型構造函數的內部調用超類型的構造函數。寄生式繼承這種繼承方式是把原型式工廠模式結合起來,目的是為了封裝創建的過程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對象間的繼承) 類式繼承(構造函數間的繼承) 由于js不像java那樣是真正面向對象的語言,js是基于對象的,它沒有類的概念。...
摘要:一些面向對象語言中支持多繼承,在也能實現多繼承,但是有一些局限,因為在中繼承是依賴原型鏈實現的,只有一條原型鏈,所以理論上是不能繼承多個父類的。從第一個參數起為被繼承的對象獲取參數長度緩存參數對象緩存當前對象遍歷被繼承對象中的屬性 一些面向對象語言中支持多繼承,在JavaScript也能實現多繼承,但是有一些局限,因為在JavaScript中繼承是依賴原型prototype鏈實現的,只...
摘要:的繼承方式屬于原型式繼承,非常靈活。當使用關鍵字執行類的構造函數時,系統首先創建一個新對象,這個對象會繼承自構造函數的原型對象新對象的原型就是構造函數的屬性。也就是說,構造函數用來對生成的新對象進行一些處理,使這個新對象具有某些特定的屬性。 繼承這個東西在Javascript中尤其復雜,我掌握得也不好,找工作面試的時候在這個問題上栽過跟頭。Javascript的繼承方式屬于原型式繼承,...
摘要:雖然,也是面向疾苦的語言,但是,它和靜態類型語言的面向接口編程不一而足。對象對他自己的行為負責,其他對象不關心它的內部實現。 ‘工欲善其事,必先利其器’,在深入學習JavaScript之前,我認為我們很有必要了解以下,JavaScript這門面向對象的動態語言到底是一門什么樣的語言。 JavaScript vs 其他面向對象語言 它沒有使用像Java等傳統的面向對象語言的類式繼承,而...
閱讀 1336·2023-04-25 23:47
閱讀 912·2021-11-23 09:51
閱讀 4432·2021-09-26 10:17
閱讀 3706·2021-09-10 11:19
閱讀 3254·2021-09-06 15:10
閱讀 3546·2019-08-30 12:49
閱讀 2421·2019-08-29 13:20
閱讀 1730·2019-08-28 18:14