標籤:最好 類的屬性 nbsp test html ceo 對象冒充 這一 article
對於javascript中的繼承,因為js中沒有後端語言中的類式繼承。所以js中的繼承,一般都是原型繼承(prototype)。
function P (name){this.name = name;this.say = function(){console.log(‘p‘);}}function S (name,id){this.id = id;this.eat = function(){console.log(‘s‘);}}S.prototype = P.prototype;var s = new S();
以上代代碼存在一個重要問題:
S.prototype = P.prototype;
該句代碼會導致,在改動子類的prototype的時候,相同會影響父類的prototype元素。
解決方案一般採用new 父級對象的方式:
S.prototype = new P();
這裡涉及到new 的工作原理,new P(), 會依據P的prototype對象建立一個執行個體,然後將構造方法中的成員變數和成員方法設定進去。
此種方式, 改動子類的prototype則不會影響父類的prototpye(因為是建立了一個對象,不再是指向同一個prototype).
設定prototype之後。還須要重設子類S的contrustor,讓其重指向 S。而不是new P() 所相應的construstor. 例如以下:
S.prototype.constructor = S;
非常多時候這裡不重設。不會出現故障,可是假設後面須要用到constructor 來建立執行個體,或者判定執行個體類型,則會出現錯誤。
所以這裡最好是重設。
上面所述的原型繼承。儘管能夠通過JavaScript原型繼承,可是相同存在不足。
此種繼承方式。不可以繼承在構造方法設定的成員變數和成員方法。僅僅能繼承在原型中設定的方法,或者屬性。
如:
var s = new S(‘yang‘,‘01‘);
當中的第一個參數,並不能傳遞給到name屬性。
於是引出另外一種繼承方式: 對象冒充。
function P (name){this.name = name;this.say = function(){console.log(‘p‘);}}function S (name,id){P.call(this,name);this.id = id;this.eat = function(){console.log(‘s‘);}}var s = new S(‘yanghi‘,‘test‘);
在子類構造方法中,借用父類的構造方法。使子類具有父類的屬性和方法。
例如以下:
P.call(this,name);
該句代碼與例如以下效果一樣:
this.name = name;this.say = function(){}
從而將父類的屬性複製到子類中。從而實現對象冒充。
那麼該此種對象冒充方式。相同存在問題:
1 無法繼承原型prototype中的屬性和主法。
2 構造方法的成員方法在父類和子類中都會有一份拷貝,造成記憶體的添加。
所以最好的實現方式是:
1 對原型對象。採用原型繼承
2 構造方法中的屬性和方法。採用對象冒充。
這也是當前絕大對數的js繼承庫所採用的實現方式。例如以下:
function P (name){this.name = name;}P.prototype.say = function(){console.log(‘say‘);}function S (name,id){P.call(this,name);this.id = id;}function Bare(){}Bare.prototype = P.prototype;S.prototype = new Bare();S.prototype.constructor = S;S.prototype.eat = function(){console.log(‘eat‘);}var s = new S(‘yanghi‘,‘test‘);
這裡的成員屬性。採用對象冒充,成員方法採用原型繼承。
注意一點。這裡實現原型繼承須要採用一個中間變數。例如以下:
S.prototype = new Bare();
假設不採用中間變數。直接new P() 的話,會出現故障。
因為new 會依照P的prototype對象模版,建立一個對象,這一步沒有問題。
可是接下來。它會將P構造方法的成員屬性也設定到這個對象中,就會導致對這個對象汙染。
這裡我們僅僅須要它的prototype就能夠了。其他的成員變數採用對象冒充的方式就能夠了。
第三種實現繼承方式,採用ES5 Object.create實現。
//Shape - superclassfunction Shape() { this.x = 0; this.y = 0;}Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info("Shape moved.");};// Rectangle - subclassfunction Rectangle() { Shape.call(this); //call super constructor.}Rectangle.prototype = Object.create(Shape.prototype);var rect = new Rectangle();rect instanceof Rectangle //true.rect instanceof Shape //true.rect.move(1, 1); //Outputs, "Shape moved."
只是此方式最大的問題還是相容性,須要 IE 9 + , safari 5 +,opera 11.6 +
以上就是對象繼承的一些問題,以記錄之,謹防忘記。
[ JavaScript ] JavaScript 實現繼承.