前置任務
在說原型物件是什么之前,我們先討論一下物件是什么東西
在說物件是什么之前,我們又得討論一下參考型別
參考型別


首先,js 中變數的值分兩種型別
- 參考型別
- 值型別
關于這兩種型別,我們需要從記憶體的角度來看
var num = 9527 //值型別
var str = "一段字串" // 值型別
var obj = { // 參考型別
attr_1:"qwer",
attr_2:"df"
}
上面這些資料,在記憶體中可能是這樣的

可以看到
- 值型別的
num和str兩個變數,變數名直接對應具體值 - 參考型別的
obj這個變數對應的是一段地址,而這個地址的位置存的才是真正的obj的具體值(物件)
至于為什么要這么存,這跟記憶體的管理有關就不展開說,簡單的
你媽媽給你生了五個可愛的妹妹
for(var i=0;i<5;i++){
var 妹妹i號=new 妹妹()
}
每個妹妹都是new出來的一個物件,她們都有一些屬性,比如
妹妹1號:{
age:3
name:妹妹1號,
parent:{
媽媽:你的媽媽,
爸爸:你的爸爸
}
}
每個妹妹的
age和name屬性都是不同的,而parent屬性都是相同的,這時候如果每個妹妹都存一份parent就太浪費記憶體了,所以我們可以存個地址.記憶體中這個地址的位置存真正的parent資訊,這樣就可以很好的利用起寶貴的記憶體空間啦
ps: 我們建立一個概念,一個物件是一個獨立的'塊',而不是妹妹i號.parent這樣一條屬性,妹妹i號.parent這條屬性指向一個物件,也不用糾結,先往下看
物件
前面我們說了,物件是獨立的塊記憶體,要想訪問或者操作物件,就得通過該物件的的地址,而變數存盤的就是這個地址
然后我們來看
var obj = {
attr_1: "qwer",
attr_2: "df"
};
var obj_2=obj
obj_2.attr_1="qwqaqaaaaaawer"
console.log(obj.attr_1) //qwqaqaaaaaawer
這樣,為什么改的是obj_2.attr_1而列印obj.attr_1的時候是qwqaqaaaaaawer應該就很清楚了
原型物件
無論什么時候,只要創建了一個新函式,就會根據一組特定的規則為該函式創建一個 prototype 屬性,這個屬性指向函式的原型物件,
注意兩點
- 函式的
prototype屬性指向函式的原型物件,而不是說prototype就是原型物件,prototype是地址,記憶體中這個地址的位置上的東西才是原型物件- 函式也是物件,所以函式也可以有屬性

拓展閱讀: 為什么要創建原型物件
在默認情況下,所有原型物件都會自動獲得一個 constructor(建構式)屬性,這個屬性包含一個指向 prototype 屬性所在函式(下圖這個例子中的a)的地址,看圖理解:

到目前為止,記憶體中是這樣的
思考題:為什么a.prototype.constructor==a
答案:a.prototype.constructor和a指向同一塊記憶體
上面說,創建了自定義的建構式之后,其原型物件默認會取得 constructor 屬性

然鵝:


這個a.prototype.toString函式根本沒有定義,上面的記憶體圖中也看不到它,那它是從哪哪冒出來的???
至于其原型物件的其他方法,則都是從 Object 繼承而來的,

(這個__proto__是什么,看下面的詳細講解)
當呼叫建構式創建一個新實體后(是一個物件),該實體的內部將包含一個指標(內部屬性),指向建構式的原型物件,
es5 中管這個指標叫[[Prototype]],雖然在 js 中沒有標準的方式訪問[[Prototype]],
但 Firefox、Safari 和 Chrome 在每個物件(函式的原型物件也是物件,所以也有__proto__屬性)上都支持一個屬性__proto__;
再來看一遍這段代碼:
a.prototype指向原型物件,原型物件是由建構式Ojbect生成的Object也是一個函式,是Object.prototype指向Object的原型物件- 思考題:
a.prototype.__proto__是函式a的原型物件的一條屬性,這個屬性的屬性值是一個地址,那么記憶體中這個地址存的是什么?
答案: 存的是Object的原型物件
附記憶體圖一張,方便理解:
這個連接存在于實體的原型物件與建構式的原型物件之間,而不是存在于實體與建構式之間,
a的原型物件是由建構式Object生成的,他們兩個之間存在鏈接(通過__proto__)
接著說,js中,有這樣一條規則:訪問一條屬性(假設是屬性attr)時,在當前物件(假設是obj)中找不到的,就往obj.__proto__找,即obj.__proto__.attr,再找不到,就往obj.__proto__.__proto__找,直到找到或者obj.__proto__.......為null才停止
所以 前面的a.prototype.toString實際上是a.prototype.__proto__.toString也就是Object.tostring
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/145150.html
標籤:JavaScript
下一篇:Ajax-原生JS中的Ajax




