可視化網(wǎng)站制作軟件站長之家ppt素材
1.prototype解釋
在JavaScript中,prototype對象是實(shí)現(xiàn)面向?qū)ο蟮囊粋€重要機(jī)制。
每個函數(shù)就是一個對象(Function),函數(shù)對象都有一個子對象 prototype對象,類是以函數(shù)的形式來定義的。prototype表示該函數(shù)的原型,也表示一個類的成員的集合。
在通過new創(chuàng)建一個類的實(shí)例對象的時候,prototype對象的成員都成為實(shí)例化對象的成員。
1、該對象被類所引用,只有函數(shù)對象才可引用;
2、在new實(shí)例化后,其成員被實(shí)例化,實(shí)例對象方可調(diào)用。
同時,函數(shù)是一個對象,函數(shù)對象若直接聲明成員,不用被實(shí)例化即可調(diào)用。
上面兩點(diǎn)很重要,第一點(diǎn)(該對象被類所引用,只有函數(shù)對象才可引用): 只有當(dāng)一個對象被定義為函數(shù)對象時,才擁有對prototype對象引用的prototype屬性,這點(diǎn)必須知道,因?yàn)檫@牽涉到了new一個對象的過程中js引擎要完成對prototype進(jìn)行一系列操作,而普通的js對象由于并不能被new,即使擁有prototype也是無意義的;第二點(diǎn)在我之前的文章中已討論過( 改變this的引用,為實(shí)例對象直接定義成員屬性),所以若直接在函數(shù)對象中聲明成員,無法被實(shí)例對象訪問。
2.prototype作用
上面說了prototype的一些定義,那么prototype有什么作用。上一段落中其中解釋了prototype的作用,“ 通過new創(chuàng)建一個類的實(shí)例對象時,prototype對象的成員都成為實(shí)例化對象的成員”,意思就是我們可以為new創(chuàng)建的實(shí)例對象動態(tài)添加成員變量,而無需在函數(shù)對象中定義所有的屬性和方法。如下代碼:
function animal(){}animal.prototype.name = "animal";
animal.prototype.move = function(){alert("i can move");
}var animalObj = new animal();
alert(animalObj.name);
animalObj.move();
運(yùn)行結(jié)果:


通過new創(chuàng)建一個函數(shù)對象的實(shí)例對象時,該函數(shù)對象的prototype原型對象的成員都能被實(shí)例對象訪問。之前在我的前一篇文章中《 js中this關(guān)鍵字探討》就模擬了一下new一個對象的過程,但是當(dāng)時我們并沒有涉及到prototype對象,那么涉及到了prototype對象,這個過程又到底是怎么實(shí)現(xiàn)的呢?
3.new過程中對prototype對象的操作
一個函數(shù)對象被new實(shí)例化成為實(shí)例對象時,可以分解為以下三步(用上面的animal對象作為例子):
第一步:定義animalObj = {};
第二步:animalObj?.__proto__ = animal.prototype;
第三步:animal.call(animalObj?);
OK,這里需要解釋一下__proto__: 每個對象都在其內(nèi)部初始化一個屬性,就是__proto__,當(dāng)訪問一個對象屬性時,如果內(nèi)部不存在這,就會去__proto__里找,__proto__又會有自己的__proto__,于是一直找下去,這就是原型鏈的概念。
當(dāng)訪問animalObj 的name和move屬性時,animalObj并沒有這些屬性,就會去__proto__中找,在第二步中,__proto__指向了animal.prototype,所以animal.prototype定義了name和move屬性,所以就可以訪問這些屬性。那么到底怎么驗(yàn)證我們對于__proto__的結(jié)論呢?
按照標(biāo)準(zhǔn)__proto__不對外公開,是個私有屬性,但chrome的引擎將其暴露出來成一個共有的屬性,可對外訪問和設(shè)置,IE不能直接訪問,如下:
alert(animalObj.__proto__ === animal.prototype);
運(yùn)行結(jié)果:

總結(jié):當(dāng)一個函數(shù)對象被被new為一個實(shí)例對象時,函數(shù)對象的prototype對象中的屬性并沒有直接成為實(shí)例對象的成員屬性,而是成為實(shí)例對象的__proto__對象中的屬性,而函數(shù)對象中的成員(需要使用this關(guān)鍵字)會被改變引用直接成為實(shí)例對象的成員屬性
4.prototype擴(kuò)展:實(shí)現(xiàn)js對象的繼承
上面說到,當(dāng)訪問一個對象的成員屬性時,如果對象本身沒有該屬性時,會去它的__proto__對象中找,如果找不到,繼續(xù)找__proto__的__proto__對象中的屬性,一直往下找。可以利用這一特性,實(shí)現(xiàn)類似于java中的繼承,如下代碼:
// 動物"類"(構(gòu)造函數(shù))
function animal(){}animal.prototype.name = "animal";
animal.prototype.move = function(){alert("i can move");
}// 定義一個cat對象,繼承animal中的成員
function cat(){}//prototype實(shí)現(xiàn)繼承
cat.prototype = new animal();// 為cat.prototype增加成員
cat.prototype.detail = "I am a cat , I am also an animal";// cat的實(shí)例對象,訪問成員屬性
var c = new cat();
alert(c.detail);
alert(c.name);
c.move();
運(yùn)行結(jié)果:



過程拆分:
1.var a = new animal(); 得出a.__proto__ = animal.prototype
2.cat.prototype = a,cat.prototype.__proto__ = a.__proto__
3.var c = new cat(),得出c.__proto__ = cat.prototype,所以c.__proto__.__proto__ = animal.prototype;
所以,當(dāng)訪問c的detail時,本身找不到該屬性,會找__proto__(即cat.prototype)中是否有該屬性,找到了該屬性,同理,訪問name和move屬性時,會繼續(xù)往下遍歷__proto__中是否有該屬性。
這也就是原型鏈的實(shí)現(xiàn)原理。本質(zhì)上prototype只是一個假象,在實(shí)現(xiàn)原型鏈中只起到輔助作用,只是在new的時候有價值,原型鏈的本質(zhì),其實(shí)在于__proto__
👉👉👉 自己搭建的租房網(wǎng)站:全網(wǎng)租房助手,m.kuairent.com,每天新增 500+房源