JS對象繼承方式
摘自《JavaScript的對象繼承方式,有幾種寫法》,作者:peakedness
鏈接:https://my.oschina.net/u/3970421/blog/2872629
方式一:對象冒充
原理:構造函數使用this關鍵字給所有屬性和方法賦值(即采用類聲明的構造函數方式)。因為構造函數只是一個函數,所以可使Parent構造函數稱為Children的方法,然后調用它。Children會收到Parent的構造函數中定義的屬性和方法。
//父類構造函數
var Parent = function(name){
this.name = name;
this.sayHi = function(){
console.log("Hi" + this.name + ".");
}
}
var Children = function(name){
this.method = Parent;
this.method(name); //實現繼承
delete this.method;
this.getName = function(){
console.log(this.name);
}
}
var P = new Parent("john");
var C = new Children("joe");
P.sayHi(); //Hi john
C.sayHi(); //Hi joe
C.getName(); //joe
方式二:原型鏈繼承
原理:JS是一門基於原型的語言。在JS中prototype對象的任何屬性和方法都被傳遞給那個類的所有實例。
//父類構造函數
var Parent = function(name){
this.name = name;
this.sayHi = function(){
console.log("Hi" + this.name + ".");
}
}
//子類構造函數
var Children = function(){};
Children.prototype = new Parent();
var P = new Parent();
var C = new Children();
P.sayHi();
C.sayHi();
注意:
調用Parent的構造函數,沒有給它傳遞參數。這是原型鏈中的標准做法,要確保構造函數沒有任何參數。
方式三:使用call或apply方法
原理:通過改變this指向實現繼承。apply第二個參數必須是數組,call依次傳入。
//父類構造函數
var Parent = function(name){
this.name = name;
this.sayHi = function(){
console.log("Hi" + this.name + ".");
}
};
//子類構造函數
var Children = function(name){
Parent.call(this,name);
this.getName = function(){
console.log(this.name);
}
};
var C = new Children("Joe");
C.sayHi(); //Hi john
C.getName(); //Joe
方式四:混合使用(推薦)
使用原型鏈就無法使用帶參數的構造函數了
因此,在JS中創建類,最好使用構造函數定義屬性,使用原型鏈定義方法。
//父類構造函數
var Parent = function(name){
this.name = name;
}
Parent.prototype.sayHi = function(){
console.log("Hi ! " + this.name + "!!!");
}
var P = new Parent("John");
P.sayHi(); //Hi John !!!
方式五:使用Object.create方法
Object.create方法會使用指定的原型對象及其屬性去創建一個新的對象
//父類構造函數
var Parent = function(name){
this.name = name;
}
Parent.prototype.sayHi = function(){
console.log("Hi " + this.name + ".");
}
//子類構造函數
var Children = function(name,age){
this.age = age;
Parent.call(this,name); //屬性不在prototype上
};
Children.prototype = Object.create(Parent.prototype);
Children.prototype.constructor = Children;
Children.prototype.getAge = function(){
console.log(this.age);
};
var P = new Parent("John");
var C = new Children("Joe",30);
P.sayHi(); //Hi John
C.sayHi(); //Hi Joe
C.getAge(); //30
注意:
當執行Children.prototype = Object.create(Parent.prototype)這個語句后,Children的constructor就被變為Parent,因此需要將Children.protype.constructor重新指定為Children本身。
constructor指向創建此對象的函數的引用。
方式六:extends關鍵字實現繼承
class Paren{
constructor(name,age){
this.name = name;
this.age = age;
}
}
class Children extends Parent{
constructor(name,age,job){
super(name,age); //super必須在前,否則代碼報錯
this.job = job;
}
}
注意:
子類的constructor方法沒有調用super之前,就使用this關鍵字會報錯。原因是:子類Children的構造函數之中的super(),代表調用父類Parent的構造函數。
super雖然代表了父類Parent的構造函數,但是返回的是子類Children的實例,即super內部的this指的是Children,因此super()在這里相當於Parent.prototype.constructor.call(this);