JS原型和原型鏈的理解


構造函數創建對象

我們首先使用構造函數來創建一個對象。

function A () {

};

let a = new A();
a.value = 'a';
console.log(a.value); //輸出的結果為a.

prototype

每一個函數都會有一個prototype屬性(只有函數才具有的屬性),prototype屬性指向的是調用構造函數創建的實例的原型。原型指的是每一個javascript對象在創建的時候(null除外)都會與之關聯的另一個對象。而每一個對象都會從原型中繼承該屬性。

 

function A () {

};

A.prototype.value = 'A';
let a1 = new A();
let a2 = new A();
a1.value = 'a1';

console.log(a1);    //輸出a1 --來自實例。
console.log(a2);    //輸出A --來自原型。

delete a1.value;
console.log(a1);    //輸出A --來自原型。

在以上例子中,需要訪問a1中的value時,會在這該對象中搜索名為value的屬性,因為value在該對象中的確存在,因此直接返回該值而不必再去搜索原型;同樣的因為在a2中不存在value,因此會向上搜索原型,結果在原型中查找出了value屬性。

當在對象中添加一個屬性時,這個屬性就會屏蔽在原型對象中保存的同名屬性(a1中的value屏蔽了A中的value)。也就是說添加了這個屬性阻止我們訪問原型中的那個屬性,但不會修改那個屬性。不過使用delete操作符則可以完全刪除實例的屬性,從而重新訪問到原型中的屬性。

用一張圖來表示構造函數和原型的關系:

 

_proto_

這是每一個對象都具有的屬性(null除外),叫做_proto_,會指向該對象的原型。

function A () {

};

let a = new A();

console.log(a.__proto__ === A.prototype);  //true

由此我們能夠更新一下關系圖得到:

 constructor

既然構造函數和實例對象都能夠指向原型,那么原型是否也包含一個屬性來指向構造函數和實例對象的呢? 指向實例對象是沒有的,因為一個構造函數可以生成多個實例對象。但是指向構造函數的卻是有一個,這就要談到今天要說的第三個屬性constructor了。每一個原型都含有一個constructor屬性用來指向關聯的構造函數。

function A() {

};

console.log(A.prototype.constructor === A);    //true

 

 

所以再次更新關系圖:

 

綜上我們可以得出一個結論就是:

function A () {

};

let a = new A();

console.log(a.__proto__ === A.prototype);    //true
console.log(A.prototype.constructor === A);     //true

 

原型的由來

原型對象是通過Object構造函數生成的,結合之前所講的_proto_指向構造函數的prototype。

function A () {

};

console.log(A.prototype.__proto__ === Object.prototype);    //true 

 

 由此我們可以得出關系圖為:

 

 

 

 接下來我們再看看Object.prototpye的原型來自什么。

console.log(Object.prototype.__proto__);    //null

 

 引用阮一峰老師的《undefined和null的區別》

null 表示“沒有對象”,即該處不應該有值。

 

所以 Object.prototype.__proto__ 的值為 null 跟 Object.prototype 沒有原型,其實表達了一個意思。

所以查找屬性的時候查到 Object.prototype 就可以停止查找了。

最后一張關系圖也可以更新為:

 

總結:

A.__proto__ === Function.prototype 
Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null 
A.protype__proto__ == Object.prototype

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM