JavaScript.prototype 和 繼承 - 01

我為什么要把 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..

image.png

到目前為止,從來都沒有人懷疑過.

這里就應(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)境中打印將會返回一個空對象)

image.png

所以,我們可以先暫時假定: 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對象繼承.

于是,可以畫一下面這張圖.

image.png
  • 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)部沒有 nameage 屬性.

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ù)刻==

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容