標籤:資訊 als 空間 實現 his cto 分享圖片 func this
首先,建立一個建構函式:
function Person(name,age){ this.name=name; this.age=age; this.eat=function(){ console.log("吃"); } }
接著,我們執行個體化兩個對象:
var stu1 = new Person("小明",20); var stu2 = new Person("小花",30);
我們調用兩個對象的eat方法:
stu1.eat(); stu2.eat();
結果肯定是:吃 吃
但是:這兩個方法不是同一個方法
console.log(stu1.eat===stu2.eat);//false
這是為什麼呢?
每個執行個體對象都有自己的eat方法,而這個eat方法不是共用的
如果我要建立100個對象,方法的實現是一樣的,但卻不能共用,豈不是很浪費空間?
天無絕人之路,通過原型的方式是可以解決的:
原型添加方法:
Person.prototype.eat=function(){ console.log("吃東西"); }
此時建構函式和原型對象中都有eat方法,預設先找建構函式,建構函式沒有找原型對象,原型對象沒有undefind
我們刪掉之前建構函式中的eat(),此時:
console.log(stu1.eat===stu2.eat);//true
原型的作用:解決資料共用,節省記憶體空間
那麼原型對象是什麼呢?
Person() 是一個建構函式,我們通過console.dir(Person),查看他的詳細資料,
發現該建構函式有一個屬性prototype,該屬性也是一個對象,標準屬性,是給程式員使用的,這個屬性叫做原型對象。
stu1是一個執行個體對象,我們通過console.dir(stu1),查看他的詳細對象
發現該執行個體對象有一個屬性__proto__,該屬性也是一個對象,非標準屬性,給瀏覽器使用的,這個屬性叫做原型對象。
從stu1的詳細中看到他並沒有eat()方法,那麼他是如何訪問這個方法的呢?
我們開啟prototype這個屬性:
執行個體對象中沒有eat(),建構函式中的prototype中有eat()
由此推出:執行個體對象的__proto__的指向和該執行個體對象所在的建構函式的prototype的指向相同,
那麼執行個體對象就可以直接存取prototype中的方法了
下面圖中的construtor是什嗎?
執行個體對象的__proto__中的constructor就是該執行個體對象所在的建構函式 建構函式中的prototype中的constructor指向的是原型對象所在的建構函式
而建構函式、執行個體對象、原型對象三者之間的關係是什麼呢?
(1)執行個體對象是通過建構函式建立的
(2)建構函式中prototype叫原型對象
(3)建構函式中的prototype中有constructor叫構造器,指向的是該原型對象所在的建構函式
(4)執行個體對象中__proto__叫原型對象
(4)執行個體對象中__proto__指向的是該執行個體對象所在的建構函式的prototype
說到這裡我們就要開始推導原型鏈了:
可以這麼理解:原型鏈就是執行個體對象和原型對象之間的一種關係
我們說:建構函式中有prototype,執行個體對象中有__proto__
執行個體對象的__proto__指向的是該執行個體對象所在的建構函式中的prototype
換句話說就是:對象的__proto__指向的肯定是某個函數的prototype
往下看:
建構函式中prototype是對象,這個prototype中有__proto__也是對象,那麼這個__proto__指向的是誰呢?
它指向的肯定是某個建構函式的prototype
此時,觀察它的構造器的指向----是Object()
那麼得出結論:
Person.prototype.__proto__===Object.prototype//true
繼續觀察Person():
我們之前說建構函式中有prototype,但是我此時也發現了建構函式中有__proto__,
既然看到了__proto__,逆推思想:說明這個函數實際上也是一個對象(因為對象中有__proto__);
所以Person()的__proto__指向的肯定是其建構函式的prototype;
對象是通過建構函式建立的,那麼Person()的建構函式又是誰呢?
看Person.__proto__.constructor的指向--------Function()
得出結論:
Person.__proto__===Function.prototype//true
這個時候我們知道了:
js中的函數實際上都是通過Function這個建構函式來建立的(來執行個體化出來的);
接下來,我們往下深挖,Function
由此推出:
Function.prototype.__proto__===Object.prototype//true
由此推出:
Function.__proto__=== Function.prototype;//true
接下來,還有最後一個Object
由此推出:
Object.__proto__=== Function.prototype;//true
Object的prototype中沒有__proto__
Object.prototype.__proto__ === null;
總結原型鏈:
解析原型鏈