js原型和原型鏈,以及__proto__、prototype屬性

__proto__和prototype屬性:

1、__proto__屬性:

在JS裏,萬物皆對象(函數是對象、原型也是對象...)。對象都具有屬性__proto__,這個屬性會指向該對象的原型。

2、prototype屬性:

除此之外,函數(Function)也是對象,而且函數除了上面說的__proto__這個屬性外,還有額外的一個prototype屬性。函數的 prototype 屬性指向了一個對象,這個對象正是調用該構造函數而創建的實例的原型,也就是下面例子中的 person1 和 person2 的原型。

那什麼是原型呢?你可以這樣理解:每一個JavaScript對象(null除外)在創建的時候就會與之關聯另一個對象,這個對象就是我們所說的原型,每一個對象都會從原型"繼承"屬性。

原型鏈:

1、函數和原型關係:

我們先使用構造函數創建一個對象,Person 就是一個構造函數(注:首字母大寫只是約定俗成,不大寫照樣可以),我們使用 new 創建了兩個實例對象 person1和persion2。

複製代碼

function Person() {
 
}
 
// prototype是函數纔會有的屬性
Person.prototype.name = 'Kevin';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // Kevin
console.log(person2.name) // Kevin

複製代碼

 

讓我們用一張圖表示構造函數和實例原型之間的關係:

 

在這張圖中我們用 Object.prototype 表示實例原型。(構造)函數有一個prototype屬性,指向了實例原型。

2、實例和原型關係:

那麼我們該怎麼表示實例與實例原型,也就是 person 和 Person.prototype 之間的關係呢?很自然,我們知道沒有對象都有__proto__屬性,而且他指向的就是對象的原型。

function Person() {
 
}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true

 

3、構造函數:

既然實例對象和構造函數都可以指向原型,那麼原型是否有屬性指向構造函數或者實例呢?指向實例倒是沒有,因爲一個構造函數可以生成多個實例,但是原型指向構造函數倒是有的,如下代碼可以驗證

function Person() {
}
console.log(Person === Person.prototype.constructor); // true

講到這裏,我們知道了函數、對象實例和原型之間的關係了,他們是通過prototype和__proto__兩個屬性聯繫起來的。如下圖

 

4、原型鏈:

原型鏈就是依託__proto__和prototype連接起來的一個原型鏈條,我們先看個例子


 

複製代碼

function Person() {
}
// 原型屬性
Person.prototype.name = ‘Jiang’
var person1 = new Person()
// 實例屬性
person1.name = ‘J’
console.log(person1.name) // J

複製代碼

 

上面代碼中在實例屬性和原型屬性都有一個名爲name的屬性,但是最後輸出來的是實例屬性上的值。

當我們讀取一個屬性的時候,如果在實例屬性上找到了,就讀取它,不會管原型屬性上是否還有相同的屬性,這其實就是屬性屏蔽,即當實例屬性和原型屬性擁有相同名字的時候,實例屬性會屏蔽原型屬性,記住只是屏蔽,不會修改,原型屬性那個值還在;但是如果在實例屬性上沒有找到的話,就會在實例的原型上去找,如果原型上還沒有,就繼續到原型的原型上去找,直到盡頭。

這個盡頭是啥?由於原型也是對象,所以也會有__proto__屬性,也就是原型的原型;最後就可以找到Object.prototype這個大boss,所有原型對象都是Object構造函數生成的(Object.prototype值爲null)。正是因爲所有的原型最終都會指向Object.prototype,所以對象的很多方法其實都是繼承於此,比如toString()、valueOf(),前面用到的hasOwnProperty,甚至是.constructor、proto

 

補充:一些常用方法:

1)檢查對象是否有該屬性:

複製代碼

function Person() {
}
var person1 = new Person()
// 實例屬性
person1.name = ‘J’
person1.hasOwnProperty(‘name’)  // true

複製代碼

注:hasOwnProperty屬性只有存在於實例中才會返回true

2)in則會遍歷所有屬性,不管是實例上的,還是原型上的:

複製代碼

function Person() {
}
Person.prototype.age = ‘100’
var person1 = new Person()
person1.name = ‘J’
 
'name' in person1 // true
'age' in person1  // true
 
for (var prop in person1) { 
        console.log(prop)  // name age
}

複製代碼

 

 

---------------------
作者:趕路人兒
來源:CSDN
原文:https://blog.csdn.net/liuxiao723846/article/details/81984357

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章