當(dāng)聲明一個對象,那么這個對象一定要找到一個公用的屬性,如果沒有公用的屬性,那么這個對象就沒啥用了,除了存數(shù)據(jù)就沒有其他的價值了,有了公用屬性之后,就可以調(diào)用各種API。
所有對象都有 toString 和 valueOf屬性,那么我們是否有必要給每個對象一個 toString 和 valueOf 呢?
明顯不需要。
JS 的做法是把 toString 和 valueOf 放在一個對象里(暫且叫做公用屬性組成的對象)
然后讓每一個對象的 __proto__存儲這個「公用屬性組成的對象」的地址。
原型就是公用屬性的意思。
下圖中公用屬性通過__proto__串起來的像鏈一樣的路線就是原型鏈。

瀏覽器一開始就在內(nèi)存里把原型給初始化好了。如下:

var a = {}
// undefined
var b = {}
// undefined
a === b
// false
a.toString === b.toString
// true
上面代碼能看出,a和b是兩個完全不一樣的對象,嚴格相等運算返回的結(jié)果都是false,但是兩者的toString是完全一樣的,因為兩個對象的toString屬性都存在同一個公用屬性里。(也就是Object的原型里)
var a = {}
// undefined
Object.prototype
// {constructor: ?, __defineGetter__: ?, __defineSetter__: ?, hasOwnProperty: ?, __lookupGetter__: ?, …}
a.__proto__ === Object.prototype
// true
上面代碼能看出,Object.prototype是Object的公用屬性的引用(不引用就要被回收了),a.__proto__也是Object的公用屬性的引用,所以嚴格相等返回的是true(必須要用公用屬性)。
var n1 = new Number(1)
// undefined
n1.__proto__ === Number.prototype
// true
n1.__proto__.__proto__ === Object.prototype
// true
上列代碼表示n1是一個對象,但是對象里面是一個數(shù)值1,所以n1.__proto__引用的公共屬性跟Number.prototype引用的是同樣的屬性,Number.prototype引用的公用屬性本身里面也有個__proto__引用Object.prototype引用到的公共屬性(具體可以看文章開頭兩幅圖來理解),所以n1.__proto__.__proto__是與Object.prototype嚴格相等的,因為引用的都是同一個公共屬性。