最近地鐵上重讀了《Javascript語言精粹和編程實踐》,又有了新的理解。
原型繼承
面向?qū)ο蟮恼Z言有三個特性,即封裝性、繼承和多態(tài)。一般來說,三個特性都滿足,即稱為“面向?qū)ο笳Z言”。
“對象系統(tǒng)”的繼承特性有三種實現(xiàn)方案,基于類(class-based)、基于原型(prototype-based)和基于元類(metaclass-based)。Javascript采用了基于原型繼承實現(xiàn)對象系統(tǒng)。采用“構(gòu)造器(constructor)”的機(jī)制實現(xiàn)類的功用。
在JavaScript中,函數(shù)創(chuàng)建之后都會有一個prototype屬性,這個屬性指向函數(shù)的原型對象,同時原型對象的 constructor屬性又指向構(gòu)造函數(shù)本身。
即:
function T(){
//構(gòu)造函數(shù)
}
T.prototype === 原型對象
T = T.prototype.constructor
在JavaScript語言和對象系統(tǒng)的實現(xiàn)中,對象(Object)并沒有原型,而構(gòu)造器有原型,屬性"<構(gòu)造器>.prototype"指向原型。對象只有“構(gòu)造自某個原型”,不存在“擁有某個原型”。
原型也是對象,即原型是對象的一個實例。原型的含義是指:如果構(gòu)造器有一個原型對象A,那么由該構(gòu)造器創(chuàng)建的實例(instance)都復(fù)制自A。所以實例繼承了A的所有屬性、方法和其他性質(zhì)。
原型也是對象實例
假設(shè)有一個構(gòu)造器T , T的原型對象為M,T是一個函數(shù)(Function),M是一個對象(OBJECT)。
即:T.prototype = M
原型對象M中含有一個constructor 屬性指向構(gòu)造器本身。
即 M.constructor = T = T.prototype.constructor
而同時原型對象 M 也是 對象(OBJECT)的一個實例。而對象(OBJECT)同時也是構(gòu)造器。那么Object 的原型對象是什么呢?實現(xiàn)一下我們可以得到:
Object.prototype // {} 空的對象
因為Object也是構(gòu)造器,即Object也是函數(shù),所以
Object.constructor // Function
而對Function來說,F(xiàn)unction也是一個函數(shù),同時也是一個構(gòu)造器,function的原型對象是
Function.prototype
我從MDN上找到一段描述:
The
**Function.prototype**property represents theFunctionprototype object.
Functionobjects inherit fromFunction.prototype.Function.prototypecannot be modified.
Function.prototype屬性存儲了Function的原型對象。Function對象繼承自Function.prototype屬性,因此,F(xiàn)unction.prototype不能被修改。
那么 ,F(xiàn)unction的原型對象Function.prototype 同時也是Object的一個實例。
原型鏈
在JavaScript,每個函數(shù)都有一個prototype屬性,指向構(gòu)造器的原型,而在對象上,都有一個隱式的__proto__屬性,指向原型。
即:__proto__ === constructor.prototype
那么構(gòu)造器 對象的(Object)的原型對象 Object.prototype 為 空的對象。
所以O(shè)ject.prototype是所有對象的根源 {}
而Function.prototype則構(gòu)造自 Object.prototype上。
Function.prototype.__proto__ = Object.prototype
而空的對象 {} (Object.prototype) 來自 null
即 Object.prototype.__proto__ === null //true
屬性查找
當(dāng)查找一個對象的屬性時,Javascript會向上遍歷原型鏈,直到找到給定名稱的屬性為止,如果查找到原型鏈頂端——Object.prototype——仍然沒有找到指定屬性,那么就會返回undefined。
對象的屬性在查找時,先查找自身的屬性,然后查找原型,再往上到Object的原型上。
hasOwnProperty函數(shù):
hasOwnProperty是Object.prototype的一個方法,它可是個好東西,他能判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,因為hasOwnProperty 是 JavaScript 中唯一一個處理屬性但是不查找原型鏈的函數(shù)。