我們創建的每個函數都有一個prototype(原型)屬性,這個屬性是一個指針,一個對象。無論什么時候,我們只要創建一個新函數,就會根據一組特定的規則為該函數創建一個prototype屬性,這個屬性對象指向函數的原型對象。在默認情況下,所有原型對象都會自動獲得一個 constroctor(構造函數)屬性,這個屬性包含一個指向prototype屬性所在函數的指針。例如:
function Person(){}
當我們創建這個Person函數(對象)的時候,該函數便有了一個prototype屬性,它的原型對象Person.prototype會獲得一個constroctor屬性,那么Person.prototype.constroctor便指向了Person。更直白一點講就是,如果我們再此基礎上再加一句
var p=new Preson();
那么,p的原型就會指向構造器的prototype屬性,也就是Person.prototype。
那么,原型鏈具體的工作機制是什么?請看下面這個例子
function foo(){} foo.prototype.z=3; var obj=new foo(); obj.y=2; obj.x=1; obj.x;//1 obj.y;//2 obj.z;//3 typeof obj.toString();//'function' 'z' in obj;//true obj.hasOwnProperty('z');//false
當輸出obj.z的時候,並不會因為obj對象沒有z屬性而輸出undefied,而是查找obj的原型也就是foo.prototype,這是js發現z的值是3,所以就會輸出obj.z的值為3.
實際上,我們用對象字面量創建的函數對象,其原型obj.prototype會指向Object.prototype,而Object.prototype也是由原型的,其值是null,這是上就是一個
原型鏈,而這也是 typeof obj.toString(); 為function的原因,因為沿着原型鏈向上查找,便找到了object中的toString方法。