實現類式繼承的目標是經過構造函數Child()獲取來自於另一個構造函數Parent()的屬性,從而建立對象。編程
1.類式繼承模式#1 —— 默認方式(原型指向父函數實例)閉包
function Parent(name) { this.name = name || 'king'; } Parent.prototype.say = function () { return this.name; }; function Child(name) { this.name = name; } function inherit(C, P) { /** * 1>該繼承模式同時繼承了兩個對象的屬性,即添加到this的屬性以及原型屬性。 * 在絕大多數的時候,並不須要這些自身的屬性,由於它們極可能是指向一個特定的實例,而不是複用。 * 可是咱們能夠提供覆蓋屬性的方式進行實例化更新。 * 2>對於構造函數的通常經驗法則是:應該將可服用的成員添加到原型中。 */ C.prototype = new P(); } inherit(Child, Parent); var child = new Child('kingChild'); console.log(child.say()); //king
2.類式繼承模式#2 —— 借用構造函數app
function Parent(name) { this.name = name || 'king'; } Parent.prototype.say = function () { return this.name; }; function Child(name) { /** * 1>優勢:能夠得到父對象自身成員的真實副本,不會存在子對象意外覆蓋父對象屬性的風險。 * 2>缺點:沒法從原型中繼承任何東西 ,它並不會爲每一個實例從新建立原型。 */ Parent.apply(this, arguments); } var child = new Child('kingChild'); console.log(child.say()); //Object #<Child> has no method 'say'
3.類式繼承模式#3 —— 借用和設置原型(調用了兩次父構造)編程語言
function Parent(name) { this.name = name || 'king'; } Parent.prototype.say = function () { return this.name; }; function Child(name) { //1>先借用構造函數 Parent.apply(this, arguments); } //2>設置子構造函數的原型使其指向父構造函數建立的新實例 Child.prototype = new Parent(); var child = new Child('kingChild'); console.log(child.say()); //kingChild
4.類式繼承模式#4 —— 共享原型函數
function Parent(name) { this.name = name || 'king'; } Parent.prototype.say = function () { return this.name; }; function Child(name) { this.name = name; } /** * 因此的對象實例實際上都共享了同一個原型。可是,這同時也是一個缺點, * 由於若是在繼承鏈下方的某處存在一個子對象或者孫子對象修改了原型,它將會影響到全部的父對象和祖先對象。 */ function inherit(C, P) { C.prototype = P.prototype; } inherit(Child, Parent); var child = new Child('kingChild'); console.log(child.say()); //kingChild
5.類式繼承模式#5 —— 臨時構造函數this
function Parent(name) { this.name = name || 'king'; } Parent.prototype.say = function () { return this.name; }; function Child(name) {} /** * 這裏的子對象僅僅繼承了父對象的原型中的屬性,這種方式是可取的,由於原型正是放置可複用功能的位置。 * 在這種模式中,父構造函數添加到this中的任何成員都不會被繼承。 */ function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); } inherit(Child, Parent); var child = new Child('kingChild'); console.log(child.name); //undefined console.log(child.say); //function () {...}
類式繼承模式 —— 總結spa
var inherit = (function () { /** * 應用閉包使得在每次須要繼承時都建立臨時(代理)構造函數。 */ var F = function () {}; return function (C, P) { F.prototype = P.prototype; C.prototype = new F(); /** * uber屬性是指向超類的指針(不使用super僅僅是由於它是關鍵字), * 這就像在其餘編程語言中訪問超類同樣,這能夠偶爾排上用場。 */ C.uber = P.prototype; /** * 充值構造函數指針 * 若是不充值該構造函數指針,那麼全部子對象將會報告Parent()是它們的構造函數,這是沒有任何用處的。 * 重置constructor屬性使其指向指望的構造函數且不會影響其功能,這是因爲該屬性主要是用於提供對象的信息。 */ C.prototype.constructor = C; } })();
源自《JavaScript模式》prototype