原型
沒錯优妙,第一次看到這張圖的我,也呆了憎账。但經過這幾天對原型的了解套硼,已經可以完全理解。
構造函數(shù)created的時候胞皱,就會有一個prototype屬性邪意,指向其原型對象九妈。原型對象有一個屬性constructor,指回其構造函數(shù)雾鬼。用構造函數(shù)new出來的實力對象萌朱,有_proto_屬性,指向其構造函數(shù)的原型策菜。
于是晶疼,對于每一個對象來說,都有一個這樣的三角關系又憨。
構造函數(shù)翠霍,本質上是Function new出來的,所以他們的_proto_都指向Function.prototype(Foo, Object, Function)竟块。
xxx.prototype壶运,原型對象,本質上是對象浪秘,所以他們的proto都指向Object.prototype(Foo.prototype, Function.prototype)蒋情。普通對象,是Object new出來的耸携,所以_proto_也指向Object.prototype棵癣。
Object.prototype._proto_ === null
由_proto_指向串聯(lián)起來的,就是原型鏈夺衍。當我們訪問對象的一個屬性時狈谊,會先看對象本身是否有這個屬性,沒有的話順著原型鏈一層層查找沟沙,直到null為止河劝。若找到,則返回該值矛紫;找不到赎瞎,則返回undefinded。
繼承
//parent構造函數(shù)
function Parent(name) {
this.name = name || 'Adam';
}
//給原型增加方法
Parent.prototype.say = function () {
return this.name;
};
//空的child構造函數(shù)
function Child(name) {}
//繼承
inherit(Child, Parent);
- 原型繼承
function inherit(C, P) {
C.prototype = new P();
}
var kid = new Child();
kid.say(); // "Adam"
kid會拿到Parent構造函數(shù)自身&原型上的值颊咬,且無法傳遞參數(shù)給父函數(shù)务甥。
- 借用構造函數(shù)
function Child(a, c, b, d) {
Parent.apply(this, arguments);
}
子對象復制了一套父構造函數(shù)自身的屬性,改動不會影響父函數(shù)喳篇。
可以傳參給父函數(shù)敞临。
子無法拿到父原型上的屬性。
- 借用并設置原型
function Child(a, c, b, d) {
Parent.apply(this, arguments);
}
Child.prototype = new Parent();
子對象獲得了父對象自己的成員麸澜,也獲得了父對象中可復用的(在原型中實現(xiàn)的)方法挺尿。
子對象也可以傳遞任何參數(shù)給父構造函數(shù)。
一個弊端是父構造函數(shù)被調用了兩次,所以不是很高效票髓。最后攀涵,(父對象)自己的屬性(比如這個例子中的name)也被繼承了兩次。
- 共享原型
function inherit(C, P) {
C.prototype = P.prototype;
}
這種模式的原型鏈很短并且查找很快洽沟,因為所有的對象實際上共享著同一個原型以故。但是這樣也有弊端,那就是如果子對象或者在繼承關系中的某個地方的任何一個子對象修改這個原型裆操,將影響所有的繼承關系中的父對象怒详。(譯注:這里應該是指會影響到所有從這個原型中繼承的對象。)
- 臨時構造函數(shù)
function inherit(C, P) {
var F = function () {};
F.prototype = P.prototype;
C.prototype = new F();
}
打斷父對象和子對象原型的直接鏈接解決了共享原型時的問題踪区,子對象只繼承原型中的屬性昆烁。