我為什么要把 javascript.prototype
原型單獨拿出一系列博客來寫?
因為平時寫js代碼的時候很少用到?。。?!
我為什么平時寫js代碼的時候很少用到?
因為平時我寫js代碼,特別是對象的時候.不出意外,99.99999%的情況都是使用字面量的寫法?。。。?/p>
var obj = {
.....
}
一個簡單的場景
我們使用字面量(99.9999%的情況都是如此)聲明一個對象.
var obj = {
name: '李四',
age: 22
}
然后調(diào)用
obj.showInfo()
不出意外,肯定報錯.且報錯信息是 obj.showInfo is not function
..
到目前為止,從來都沒有人懷疑過.
這里就應(yīng)該報錯.因為你沒有定義這個方法.
那如果我調(diào)用obj.toString()方法呢?
[object Object]
我沒有定義 toString
方法,為什么不報錯,還正確執(zhí)行了呢?
這個 toString
的方法是哪里來的?
Object.prototype
在解釋 toString
方法哪里來的之前
有一個規(guī)則需要知道: (什么是規(guī)則?規(guī)則就是你可以先不去理解,但是必須強行記憶和知道的知識)
在js中函數(shù)也是對象,所有的函數(shù)對象上會有一個
.prototype
的屬性.
Object 也是一個函數(shù),所以,它也有 .prototype
屬性.===> Object.prototype
打印一下 Object.prototype
這個對象上有哪些屬性?
(請注意,在瀏覽器環(huán)境中打印,在Node.js環(huán)境中打印將會返回一個空對象)
所以,我們可以先暫時假定: obj.toString
方法是來自 Object.prototype
對象上的.
代碼改造
之前我們的代碼是
var obj = {
name: '李四',
age: 22
}
console.log(obj.toString())
[object Object]
之前也說過,一般在書寫js代碼創(chuàng)建一個對象時.
不夸張的說 99.9999999% 的情況都是寫的對象字面量(就像上述那樣)
但實際上,這段代碼也可以改寫成這樣.
var obj = new Object()
obj.name = '李四'
obj.age = 22
我們可以理解成,對象字面量其實是一個語法糖.
它幫我們隱式的調(diào)用了 new Object()
.
所以,在我們寫js代碼利用對象字面量創(chuàng)建對象的時候,new Object() 其實無處不在(因為99.9999%的情況下,我們都是使用對象字面量來創(chuàng)建對象.反而忽略了new的存在.).
new Object()
現(xiàn)在我們知道了,使用對象字面量創(chuàng)建對象只是一個語法糖.
其內(nèi)部幫我們調(diào)用了 new Object()
.
如果要了解為什么 obj.toString()
沒問題.
還需要知道一個前置規(guī)則(第一個是:所有的函數(shù)都包含一個.prototype屬性)
所有構(gòu)造的對象(隱式或顯式(用new).都會從它的構(gòu)造函數(shù)對象的prototype對象繼承.
于是,可以畫一下面這張圖.
-
Object
是一個函數(shù),它有一個屬性叫.prototype
. -
.prototype
屬性本身也是一個對象,它也右邊那些屬性和方法. -
obj
實際上是Object
函數(shù)構(gòu)造出出來的實例.所以,根據(jù)第二條規(guī)則,通過new Object()
創(chuàng)建出來的對象,都會從Object.prototype
對象上繼承屬性和方法. - 所以,我們調(diào)用
obj.toString
實際上是調(diào)用的Object.protoype.toString
方法.
證明obj.toString === Object.prototype.toString
我們先嘗試修改一下 Object.prototype.toString
讓它專門為 obj
對象來使用.
Object.prototype.toString = function () {
console.log(this.name, this.age)
}
obj.toString()
李四 22
關(guān)于 prototype 對象屬性的COW(copy on write)
現(xiàn)在在創(chuàng)建一個對象字面量,但內(nèi)部沒有 name
和 age
屬性.
const obj2 = {}
根據(jù)上述的規(guī)則一 & 規(guī)則二.所以下列這條等式是成立的.
console.log(obj2.toString === Object.prototype.toString) // true.
如果我現(xiàn)利用 obj2
修改了 toString
函數(shù),會對 obj
產(chǎn)生影響嗎?
obj2.toString = function() {
console.log('toString函數(shù)被我重寫了.')
}
obj.toString()
結(jié)果
李四 22
除非修改 prototype 對象本身,否則繼承自這個 prototype 對象的對象,做的任何修改只會影響此對象自己.
而不會影響到其他的對象.
這個就叫做原型對象的 COW ==copy on write 寫時復(fù)刻==