您好,登錄后才能下訂單哦!
我們先來(lái)講一個(gè)故事,一個(gè)大大的池塘,里面有很多魚(yú)。這是屬于我們大家的池塘所以里面的魚(yú)我們都可以吃,但是我們也會(huì)從集市買一些魚(yú)放在家里,那么放在家里的魚(yú)肯定是屬于我們私人的,外人是不會(huì)擁有的。那么在js里我們就把這個(gè)池塘稱為原型對(duì)象,池塘里面我們所共享的魚(yú)稱為原型中的屬性及方法,而我們自己的魚(yú)稱為構(gòu)造函數(shù)中的屬性及方法,我們是什么呢?對(duì)了,我們是對(duì)象的實(shí)例。
以上是為了讓大家能夠趣味性的對(duì)prototype有一個(gè)概念,接下來(lái)就通過(guò)代碼具體總結(jié)一下prototype~
一、理解prototype
我們創(chuàng)建的每一個(gè)函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指向?qū)ο蟮闹羔槨?/p>
構(gòu)建對(duì)象中有一種模式叫做原型模式,意思是將對(duì)象實(shí)例所不可共享的屬性及方法定義在構(gòu)造函數(shù)中,而將可共享的屬性及方法放在原型對(duì)象中,也就是prototype指向的對(duì)象中。以下是用原型模式創(chuàng)建的一個(gè)對(duì)象:
function person(name, age) { this.name = name; this.age = age; } person.prototype = { sayName: function() { console.log(this.name); } }; var p1 = new person("Wind", 20); p1.sayName(); // "Wind" var p2 = new person("Nic", 20); p2.sayName(); // Nic
這里我將name、age屬性定義在構(gòu)造函數(shù)中,將sayName方法定義在原型中。所以p1和p2對(duì)象實(shí)例的內(nèi)存空間里面各有一份name和age,但是它們卻共享一份sayName方法,意思是它們調(diào)用的sayName方法是同一個(gè)。
試想如果我們不用prototype,而是直接將sayName寫(xiě)進(jìn)構(gòu)造函數(shù)呢?
那么p1和p2中將各有一份sayName,這樣浪費(fèi)內(nèi)存空間,所以用prototype的好處之一:提高了代碼的復(fù)用性,減少內(nèi)存。
在了解原型對(duì)象的同時(shí)我們還有一個(gè)小知識(shí)要明白:每當(dāng)代碼讀取一個(gè)對(duì)象屬性的時(shí)候會(huì)執(zhí)行一次搜索,搜索目標(biāo)是給定名字的屬性,搜索路徑為:
對(duì)象實(shí)例本身---->原型對(duì)象---->對(duì)象所繼承的父類對(duì)象---->父類對(duì)象原型...---->原型鏈末端
二、prototype的注意點(diǎn)
1、不可變性:盡管prototype是共享的,但不能通過(guò)對(duì)象實(shí)例重寫(xiě)原型中的值,但是可以由對(duì)象統(tǒng)一改。通俗一點(diǎn):只能爸爸統(tǒng)一改,不能兒子改。(這也和類型有關(guān)系,孩子不能改變基本類型的值,但是可以改變對(duì)象,比如數(shù)組)
基本類型:
function person() {} person.prototype = { num: 0 }; var p1 = new person(); var p2 = new person(); p1.num++; p2.num; // 0
非基本類型:
function person() {} person.prototype = { num: [1,2,3] }; var p1 = new person(); var p2 = new person(); p1.num[2] = 8; p2.num; // [1, 2, 8] 改變了
2、同名覆蓋性:如果我們?cè)趯?shí)例中添加了一個(gè)與原型屬性同名的屬性,那么該屬性會(huì)創(chuàng)建到對(duì)象實(shí)例中并且會(huì)覆蓋掉原型中的相應(yīng)屬性。
function person(name) { this.name = name; } person.prototype = { age: 18 9 }; var p1 = new person("Wind"); var p2 = new person("Nic"); p1.age = 20; p1.age; // 20 p2.age; // 18
3、使用對(duì)象字面量創(chuàng)建原型方法,會(huì)切斷之前的鏈而重寫(xiě)原型鏈
function person(name) { this.name = name; } person.prototype = { sayName: function() { console.log(this.name); } }; var p1 = new person("Wind"); person.prototype = { age = 20 }; p1.sayName(); // error
因?yàn)閜rototype指針指向了一個(gè)新的對(duì)象,切斷了構(gòu)造函數(shù)與之前的prototype舊對(duì)象的聯(lián)系,所以p1不能調(diào)用了它。那么p1調(diào)用新對(duì)象的屬性呢?
p1.age; // error
所以我做了一個(gè)大膽的猜測(cè),就是以前包含sayName的舊對(duì)象被“拋棄”了,也就是被內(nèi)存回收了,然而p1的prototype指針指向的依舊是舊對(duì)象,所以會(huì)產(chǎn)生error。
三、總結(jié)
prototype的用法:構(gòu)造函數(shù)模型用于定義實(shí)例的屬性,而原型模型用于定義方法和共享的屬性。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持億速云!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。