題目一:
//有關於原型繼承的代碼如下:
function Person(name) {
this.name = name;
}
Person.prototype = {
getName : function() {
return this.name;
}
}
function Student(name, id) {
Person.call(this, name)
this.id = id;
}
//接下來的一行,我們提供了有三種寫法:
//第一種:Student.prototype = Person.prototype;
//第二種:Student.prototype = new Person();
//第三種:Student.prototype = Object.create(Person.prototype);
Student.prototype.getId = function() {
return this.id;
}
//請問:
//1.請簡述代碼中注釋處的三種寫法的每一種,是否正確,是否完美.如果都不夠完美,那你應該如何寫.
//2.除了注釋處,代碼的其他部分還有值得優化的地方么.
function Person(name) {
this.name = name;
}
Person.prototype = {
getName : function() {
return this.name;
}
}
function Student(name, id) {
Person.call(this, name)
this.id = id;
}
//接下來的一行,我們提供了有三種寫法:
//第一種:Student.prototype = Person.prototype;
//第二種:Student.prototype = new Person();
//第三種:Student.prototype = Object.create(Person.prototype);
Student.prototype.getId = function() {
return this.id;
}
//請問:
//1.請簡述代碼中注釋處的三種寫法的每一種,是否正確,是否完美.如果都不夠完美,那你應該如何寫.
//2.除了注釋處,代碼的其他部分還有值得優化的地方么.
My Answer:
1.這三種寫法,寫法一是錯誤的,寫法二三是正確的。
對於寫法一,只是把Person的原型對象賦值給了Student的原型對象,這樣子雖然Student的實例中可以訪問到Person的原型上的屬性和方法,但是對於不是綁定在原型上的屬性,例如Person中的this.name,實例中是不會有這個屬性的。所以這並不是繼承。只是簡單的引用,因為Person.prototype是一個對象,也是引用類型,這樣的賦值只是把Person.prototype的引用賦值給了Student.prototype。既然是引用,那兩者如果有一方發生改動,另一方必然會受影響。這樣new出來的實例之間也是互相影響的。
對於寫法二,確實是正確的寫法,這種寫法就是組合繼承,但是不是完美的寫法。因為創建實例的過程中兩次調用了父類的構造函數。
對於寫法三,也是正確的寫法,這種寫法就是寄生式繼承。但是不是完美的寫法。首先,ES3中沒有Object.create()方法,沒有做兼容。然后,這種繼承如果父類中含有引用類型,如數組,那么繼承之后,各個實例中的這個引用類型會互相影響。
相對更完美的寫法:
function inheritPrototype(SubType,SuperType){ var prototype; if(typeof Object.create==='function'){ prototype=Object.create(SuperType.prototype); }else{ funciont W(){}; W.prototype=SuperType.prototype; prototype=new W(); } prototype.constructor=SubType;
Student.prototype=prototype; }
inheritPrototype(Student,Person);
題目二,感覺給出了寫法就是可以用來回答題目二的了。不過,還要優化的話,我想應該是這里
Person.prototype = { getName : function() { return this.name; } }
這里重新定義了原型對象,覆蓋了原來的constructor屬性,可以把它定義回去。就是這樣
Person.prototype = { constructor:Person, getName : function() { return this.name; } }