摘要:一何為繼承繼承,是子類繼承父類的特征和行為,使得子類對象具有父類的實例域和方法。目的是通過繼承該父類,產出計算機子類。將父類的原型傳遞給子類使用操作符對父類進行實例化并將實例對象賦值給子類的。
本文講述JavaScript中類繼承的實現方式,并比較實現方式的差異。一、何為繼承
繼承,是子類繼承父類的特征和行為,使得子類對象具有父類的實例域和方法。1.1 優點
繼承是面向對象編程中,不可或缺的一部分。
減少代碼冗余 父類可以為子類提供通用的屬性,而不必因為增加功能,而逐個修改子類的屬性
代碼復用 同上
代碼易于管理和擴展 子類在父類基礎上,可以實現自己的獨特功能
1.2 缺點耦合度高 如果修改父類代碼,將影響所有繼承于它的子類
影響性能 子類繼承于父類的數據成員,有些是沒有使用價值的。但是,在實例化的時候,已經分配了內存。所以,在一定程度上影響程序性能。
二、例子例子以圖書館中的書入庫歸類為例。
以下是簡化后的父類Book(也可稱為基類)。
目的是通過繼承該父類,產出Computer(計算機)子類。
并且,子類擁有新方法say,輸出自己的書名。
function Book(){ this.name = ""; // 書名 this.page = 0; // 頁數 this.classify = ""; // 類型 } Book.prototype = { constructor: Book, init: function(option){ this.name = option.name || ""; this.page = option.page || 0; this.classify = option.classify || ""; }, getName: function(){ console.log(this.name); }, getPage: function(){ console.log(this.page); }, getClassify: function(){ console.log(this.classify); } };
接下來會講解子類Computer幾種繼承方式的實現和優化方法。開始飆車~
三、實例式繼承function Computer(){ Book.apply(this, arguments); } Computer.prototype = new Book(); Computer.prototype.constructor = Computer; Computer.prototype.init = function(option){ option.classify = "computer"; Book.prototype.init.call(this, option); }; Computer.prototype.say = function(){ console.log("I"m "+ this.name); }3.1 調用父類構造器進行初始化
function Computer(){ Book.apply(this, arguments); }
Computer的構造函數里,調用父類的構造函數進行初始化操作。使子類擁有父類一樣的初始化屬性。
3.2 將父類的原型傳遞給子類Computer.prototype = new Book();使用new操作符對父類Book進行實例化,并將實例對象賦值給子類的prototype。
這樣,子類Computer就可以通過原型鏈訪問到父類的屬性。
父類Book的構造函數被執行了2次
一次是在Computer的構造函數里Book.apply(this, arguments);
一次是在Computer.prototype = new Book();
這種模式,存在一定的性能浪費。
父類實例化無法傳參
Computer.prototype = new Book();,這種實例化方式,無法讓Book父類接收不固定的參數集合。
四、原型式繼承function Computer(){ Book.apply(this, arguments); } Computer.prototype = Object.create(Book.prototype); Computer.prototype.constructor = Computer; Computer.prototype.init = function(option){ option.classify = "computer"; Book.prototype.init(option); }; Computer.prototype.say = function(){ console.log("I"m "+ this.name); }
這里的改進:是使用Object.create(Book.prototype)。它的作用是返回一個繼承自原型對象Book.prototype的新對象。且該對象下的屬性已經初始化。
用Object.create生成新對象,并不會調用到Book的構造函數。
這種方式,也可以通過原型鏈實現繼承。
由于低版本的瀏覽器是不支持Object.create的。所以這里簡單介紹下兼容版本:
Object.create = function(prototype){ function F(){} F.prototype = prototype; return new F(); }
原理是定義一個空的構造函數,然后修改其原型,使之成為一個跳板,可以將原型鏈傳遞到真正的prototype。
六、函數化繼承上述兩種實現方式,都存在一個問題:不存在私有屬性和私有方法。也就是說,存在被篡改的風險。
接下來就用函數化來化解這個問題。
function book(spec, my){ var that = {}; // 私有變量 spec.name = spec.name || ""; // 書名 spec.page = spec.page || 0; // 頁數 spec.classify = spec.classify || ""; // 類型 var getName = function(){ console.log(spec.name); }; var getPage = function(){ console.log(spec.page); }; var getClassify = function(){ console.log(spec.classify); }; that.getName = getName; that.getPage = getPage; that.getClassify = getClassify; return that; } function computer(spec, my){ spec = spec || {}; spec.classify = "computer"; var that = book(spec, my); var say = function(){ console.log("I"m "+ spec.name); }; that.say = say; return that; } var Ninja = computer({name: "JavaScript忍者秘籍", page: 350});
函數化的優勢,就是可以更好地進行封裝和信息隱藏。
也許有人疑惑為什么用以下這種方式聲明和暴露方法:
var say = function(){ console.log("I"m "+ spec.name); }; that.say = say;
其實是為了保護對象自身的完整性。即使that.say被外部篡改或破壞掉,function computer內部的say方法仍然能夠正常工作。
另外,解釋下that、spec和my的作用:
that是一個公開數據存儲容器,暴露出去的數據接口,都放到這個容器
spec是用來存儲創建新實例所需的信息,屬于實例之間共同編輯的數據
my是用來存儲父類、子類之間共享的私密數據容器,外部是訪問不到的。
七、ES6繼承最后,看下現代版ES6的類繼承。不禁感慨以前的刀耕火種,是多么折磨人
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/96422.html
摘要:繼承簡介在的中的面向對象編程,繼承是給構造函數之間建立關系非常重要的方式,根據原型鏈的特點,其實繼承就是更改原本默認的原型鏈,形成新的原型鏈的過程。 showImg(https://segmentfault.com/img/remote/1460000018998684); 閱讀原文 前言 JavaScript 原本不是純粹的 OOP 語言,因為在 ES5 規范中沒有類的概念,在 ...
摘要:的繼承方式屬于原型式繼承,非常靈活。當使用關鍵字執行類的構造函數時,系統首先創建一個新對象,這個對象會繼承自構造函數的原型對象新對象的原型就是構造函數的屬性。也就是說,構造函數用來對生成的新對象進行一些處理,使這個新對象具有某些特定的屬性。 繼承這個東西在Javascript中尤其復雜,我掌握得也不好,找工作面試的時候在這個問題上栽過跟頭。Javascript的繼承方式屬于原型式繼承,...
摘要:繼承方式繼承方式限定了基類成員在派生類中的訪問權限,包括公有的私有的和受保護的。所以子類給父類引用賦值也是可以的,相當于給子類對象中繼承的父類部分起了別名。如圖成員函數也是如此,當子類與父類具有函數名相同的函數時,還是符合就近原則。 ...
摘要:子類不是父類實例的問題是由類式繼承引起的。所以寄生式繼承和構造函數繼承的組合又稱為一種新的繼承方式。但是這里的寄生式繼承處理的不是對象,而是類的原型。看上去略微復雜,還得好好研究。 寄生組合式繼承(終極繼承者) 前面學習了類式繼承和構造函數繼承組合使用,也就是組合繼承,但是這種繼承方式有個問題,就是子類不是父類的實例,而子類的原型是父類的實例。子類不是父類實例的問題是由類式繼承引起的。...
閱讀 3840·2021-10-12 10:12
閱讀 1471·2021-10-11 10:58
閱讀 2307·2021-10-09 10:01
閱讀 2620·2021-09-24 09:48
閱讀 2715·2021-09-09 11:38
閱讀 3538·2019-08-30 15:44
閱讀 1737·2019-08-30 14:22
閱讀 530·2019-08-29 12:42