對象都是通過函數建立的
function Fn() {
this.name = '王福朋';
this.year = 1988;
}
var fn1 = new
fn1是個對象,它是由函數Fn建立的,但是我要說都大家可能會反駁,不信你往下看
var obj = { a: 10, b: 20 };
var arr = [5, 'x', true];
但是不好意思,這個——真的——是一種——“快捷方式”,在程式設計語言中,一般叫做“文法糖”。
做“文法糖”做的最好的可謂是微軟大哥,它把他們家C#那小子弄的不男不女從的,本想圖個人見人愛,誰承想還得到處跟人解釋——其實它是個男孩!
話歸正傳——其實以上代碼的本質是:
//var obj = { a: 10, b: 20 };
//var arr = [5, 'x', true];
var obj = new Object();
obj.a = 10;
obj.b = 20;
var arr = new Array();
arr[0] = 5;
arr[1] = 'x';
arr[2] = true;
而其中的 Object 和 Array 都是函數:
console.log(typeof (Object)); // function
console.log(typeof (Array)); // function
可以很負責任的說——對象都是通過函數來建立的。
可以很負責任的說——對象都是通過函數來建立的。
每個對象都有一個__proto__屬性,指向建立該對象的函數的prototype。
var obj = { }
console.log(obj._proto_)
obj這個對象本質上是被Object函數建立的,是以obj.__proto__=== Object.prototype
如圖所示
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iNxQDOyUDNlRDZxUmM0EGZyYzX3MTNyQTMyIzLcdDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
即,每個對象都有一個__proto__屬性,指向建立該對象的函數的prototype。
那麼上圖中的“Object prototype”也是一個對象,它的__proto__指向哪裡?
好問題!
在說明“Object prototype”之前,先說一下自定義函數的prototype。自定義函數的prototype本質上就是和 var obj = {} 是一樣的,都是被Object建立,是以它的__proto__指向的就是Object.prototype。
但是Object.prototype确實一個特例——它的__proto__指向的是null,切記切記!
還有——函數也是一種對象,函數也有__proto__嗎?
又一個好問題!——當然有。
函數也不是從石頭縫裡蹦出來的,函數也是被建立出來的。誰建立了函數呢?——Function——注意這個大寫的“F”。
且看如下代碼。
以上代碼中,第一種方式是比較傳統的函數建立方式,第二種是用new Functoin建立。
首先根本不推薦用第二種方式。
這裡隻是向大家示範,函數是被Function建立的。
好了,根據上面說的一句話——對象的__proto__指向的是建立它的函數的prototype,就會出現:Object.__proto__ === Function.prototype。用一個圖來表示。
上圖中,很明顯的标出了:自定義函數Foo.__proto__指向Function.prototype,Object.__proto__指向Function.prototype,唉,怎麼還有一個……Function.__proto__指向Function.prototype?這不成了循環引用了?
對!是一個環形結構。
其實稍微想一下就明白了。Function也是一個函數,函數是一種對象,也有__proto__屬性。既然是函數,那麼它一定是被Function建立。是以——Function是被自身建立的。是以它的__proto__指向了自身的Prototype。