JavaScript的原型鏈算是JS比較難的一個點了。斷斷續續學習了一段時間,進過自己的思考,好像總結了一套自己的理解。
原型鏈總圖:
Js是通過對象創建對象,所以每個對象都有它的對象原型。
一、函數對象:
function Person() {
}
let UserMan = new Function();
Person和UserMan都是函數對象,他們的proto都指向函數原型對象。
console.log(UserMan.proto==Person.proto) //true
二、數組對象
let arr = new Array();
arr為數組對象,它的proto都指向數組原型對象。
三、簡單對象(可理解為字典或結構體)
1、通過Object創建對象
let obj = new Object();
obj為簡單對象
console.log(obj.proto=={}.proto) //true
2、直接字面量創建對象
let user = {
name : 'han',
introduce : function(){ console.log(this.name); }
};
user為簡單對象
console.log(user.proto=={}.proto) //true
簡單對象沒有特定的原型對象,它的proto直接指向頂層原型對象了。
3、通過Object.create創建對象
let maleUser = Object.create(user);
maleUser.__proto__ —> user
let person = {name:"alex",age:"19"};
let man = Object.create(person);
man.name = "johnny";
console.log(man.name); //johnny
console.log(man.__proto__.name); //Alex
以user作為原型,創建一個對象。
通過Object.create創建的對象,就相當于copy了一份原型對象。
4、通過函數對象創建對象
function Person() {
}
let person = new Person();
四、prototype
理順了上面各種對象后,下面開始引入prototype屬性。它是函數對象特有的一個屬性。
為什么函數對象需要這樣一個屬性呢?
我們通過Person函數對象創建一個對象person
let person = new Person();
person.name = “abc”;
這里的person明顯就是簡單對象,就是說這里通過了函數對象創建出來了簡單對象。我們知道,每個對象肯定有原型,那person的原型是什么呢,肯定不是創建它的函數對象,所以函數對象里面必須有一個屬性存儲創建的對象的原型。這里就通過prototype屬性來存儲創建對象的原型。
console.log(person.proto.proto=={}.proto) //true
回看上面的以user作為原型,創建一個對象。
那么person應該是以{}作為原型,創建的一個對象。
相當于:
let per = {};
let person = Object.create(per);
person.__proto__ —> per
拓展
更泛的理解是,通過new方式創建對象的函數對象或包裝類,都是用prototype存儲其對象真正的原型。
Function函數構造器new出來的是函數對象,所以它的Function.prototype值為函數原型對象
console.log(Function.prototype==Person.proto) //true
Array函數構造器new出來的是數組對象,所有其Array.prototype值為數組原型對象
console.log(Array.prototype==[].proto) //true
Object函數構造器new出來的是簡單對象,所有其Object.prototype值為簡單原型對象
console.log(Object.prototype=={}.proto) //true