類的設計模式:實例化欺殿、繼承和(相對)多態(tài)拔莱。
JavaScript通過原型鏈,在兩個對象之間創(chuàng)建一個關聯(lián)匿又。這樣方灾,一個對象就可以通過委托訪問另一個對象的屬性和函數(shù),從而達到“繼承”的實現(xiàn)碌更。
下面來看一個例子:
function Foo(name) {
this.name = name;
}
Foo.prototype.myName = function () {
return this.name;
};
function Bar(name, label) {
Foo.call(this, name);
this.label = label;
}
Bar.prototype = new Foo(); //實現(xiàn)prototype的關聯(lián)
Bar.prototype.myLabel = function () {
return this.label;
};
var a = new Bar("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"
構造函數(shù)和實例原型的關系圖(紅色的就是原型鏈)
image
原型prototype
每個函數(shù)都有一個prototype屬性裕偿,函數(shù)的prototype屬性指向了一個對象,這個對象正是調用該構造函數(shù)而創(chuàng)建的實例的原型痛单。例子中Bar.prototype就是實例a的原型嘿棘。
proto
這是每一個JavaScript對象(除了 null )都具有的一個屬性,叫proto旭绒,這個屬性會指向該對象的原型鸟妙。
a.__proto__ === Bar.prototype //true
Bar.prototype.__proto__ === Foo.prototype //true
constructor
constructor,每個原型都有一個 constructor 屬性指向關聯(lián)的構造函數(shù)挥吵。
Foo === Foo.prototype.constructor
為了方便理解圆仔,這里我們簡單模擬實現(xiàn)new
function objectFactory() {
var obj = new Object(),Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
var ret = Constructor.apply(obj, arguments);
return typeof ret === 'object' ? ret : obj;
};
下面介紹,另外兩種寫法:
Object.create(行為委托設計模式)
var Foo = {
init: function(name){
this.name = name;
},
myName: function(){
return this.name;
}
};
var Bar = Object.create(Foo);
Bar.setup = function(name, label){
// 委托調用
this.init(name);
this.label = label;
};
Bar.myLabel = function(){
return this.label;
};
var a = Object.create( Bar );
a.setup("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"
簡單模擬實現(xiàn)Object.create
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
class(class 語法可以簡潔地定義類方法)
class Foo {
constructor(name) {
this.name = name;
}
myName() {
return this.name;
}
}
class Bar extends Foo {
constructor(props, label) {
super(props);
this.label = label;
}
myLabel() {
return this.label;
}
}
var a = new Bar("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"