首先,在 js 中可以使用類或建構函式來建立乙個例項:
function
person()
// or
class
person
person.prototype.name =
'kevin'
;let p1 =
newperson()
;let p2 =
newperson()
;// p1.name === p2.name = 'kevin';
每個函式/類都有乙個prototype
屬性,它指向了乙個物件,這個物件就是我們呼叫這個建構函式/類而建立的例項的原型,即上面**中p1
和p2
的原型。
而原型可以這樣理解:每乙個 js 物件(null除外)在建立的時候就會與之關聯另乙個物件,這個物件就是我們所說的原型,每乙個物件都會從原型中 「繼承」 屬性。
用一張圖來表示建構函式和例項原型之間的關係:
__proto__
這個屬性,它指向該物件的原型。
如:
p1.__proto__ === person.prototype;
let n =3;
n.__proto__ === number.prototype;
因此關係圖更新為:
__proto_
屬性來獲取例項的原型之外,還能使用object.getprototypeof(p1)
(es5 的方法)來獲取物件原型:
object.
getprototypeof
(p1)
=== person.prototype;
每個原型都有乙個constructor
屬性來指向與其關聯的建構函式/類。
如:
person.prototype.constructor === person;
number.prototype.constructor === number;
因此再次更新關係圖:
原型也是乙個物件,因此我們可以使用最原始的方式建立它:
let obj =
newobject()
;
其實原型物件也就是通過object
建構函式生成的,因此原型物件的__proto__
屬性會指向建構函式的prototype
,也就是:
p1.__proto__.__proto__ === object.prototype;
// 即
person.prototype.__proto__ === object.prototype;
那麼object.prototype
的原型是什麼呢?
答案是null
:object.prototype.__proto__ === null
代表了原型鏈的盡頭。
因此關係圖可以更新為:其中由相互關聯的原型組成的鏈狀結構就是原型鏈,也就是藍色的這條線。
null
為止。
如:
object.prototype.name =
'end'
;function
person()
person.prototype.name =
'kevin'
;let p =
newperson()
;p.name =
'daisy'
;// 首先會在當前物件中查詢
console.
log(p.name)
;// daisy
// 若找不到,則去與其關聯的原型中查詢
delete p.name;
console.
log(p.name)
;// kevin
// 若其原型中也沒有,則去原型的原型中查詢
delete person.prototype.name;
console.
log(p.name)
;// end
先看個例子:
function
person()
let person =
newperson()
;person.constructor === person;
//true
根據我們前面的描述,constructor
是person
物件的原型中的屬性,person
中並沒有這個屬性;但當我們獲取person.constructor
時,會從person
的原型中讀取,而原型中正好有這個屬性,因此還是能夠正確讀取。
因此:
person.constructor === person.prototype.constructor;
絕大部分瀏覽器都支援這個非標準的方法來訪問原型,然而它並不存在於person.prototype
中,實際上,它是來自於object.prototype
,與其說是乙個屬性,不如說是乙個getter/setter
,當使用obj.__proto__
時,可以理解為返回了object.getprototypeof(obj)
。
前面有說到,每乙個物件都會從原型中 「繼承」 屬性。實際上,繼承是乙個比較迷惑的說法,在 《你不知道的 js》 中有這樣一段話:
繼承意味著複製操作,然而 js 預設並不會複製物件中的屬性,相反,js 只是在兩個物件之間建立乙個關聯,這樣,乙個物件就可以通過委託訪問另乙個物件的屬性和函式。ref:所以與其叫繼承,委託的說法反而更準確些。
原型 和 原型鏈
每乙個js物件 null除外 都和另乙個物件相關聯。另乙個 物件就是我們熟知的原型,每乙個物件都從原型繼承屬性。所有通過物件直接量建立的物件都具有同乙個原型物件,並可以通過js object.prototype 獲得對原型物件的引用。通過關鍵字new和構造函式呼叫建立的物件的原型就是建構函式的 pr...
原型和原型鏈
原型鏈 例項物件與原型之間的連線,叫做原型鏈 function human human.prototype.age 22 var a new human console.log a.age 這裡的age掛載到了human的原型上面了。其實原型就是乙個物件。a為什麼能找到原型上面的物件呢?這裡例項物件...
原型和原型鏈
建構函式 function foo name age function 其實是 var a new object 的語法糖 var a 其實是 var a new array 的語法糖 function foo 其實是 var foo new function 的語法糖 new乙個物件的過程 建立乙...