摘要:動(dòng)態(tài)原型模式是由構(gòu)造函數(shù)和原型模式組合而成的,那么構(gòu)造函數(shù)是怎樣的呢這是一個(gè)典型的構(gòu)造函數(shù),通過(guò)使用函數(shù),實(shí)例化一個(gè)對(duì)象,那么為什么可以通過(guò)使用操作符實(shí)例化對(duì)象呢,其實(shí)在使用操作符的同時(shí),系統(tǒng)會(huì)執(zhí)行以下操作執(zhí)行函數(shù)代碼首先默認(rèn)生成一個(gè)對(duì)象,
動(dòng)態(tài)原型模式是由構(gòu)造函數(shù)和原型模式組合而成的,那么構(gòu)造函數(shù)是怎樣的呢:
function Box(name){ this.name = name; this.call = function(){ alert("your name is "+ this.name) } } var box = new Box("obama");
這是一個(gè)典型的構(gòu)造函數(shù),通過(guò)使用new函數(shù),實(shí)例化一個(gè)box對(duì)象,那么為什么可以通過(guò)使用new操作符實(shí)例化對(duì)象呢,其實(shí)在使用new操作符的同時(shí),系統(tǒng)會(huì)執(zhí)行以下操作;
var box = new Object(); box.__proto__ = Box.prototype; Box.call(box); //執(zhí)行函數(shù)代碼 return box;
首先默認(rèn)生成一個(gè)對(duì)象,繼承構(gòu)造函數(shù)Box的原型,然后把函數(shù)的作用域綁定在這個(gè)對(duì)象上,在執(zhí)行函數(shù),最后返回這個(gè)對(duì)象,因此每個(gè)實(shí)例對(duì)象都是一個(gè)獨(dú)立的對(duì)象,我們知道每個(gè)對(duì)象都是不相等的;
var box1 = new Box("a"); var box2 = new box("a"); box1.call == box2.call //false
原型模式中,
function Bar(){}; Bar.prototype = { constructor:Box, age:100, call:function(){ alert("your age is" + this.age) } }
我們都知道使用字面量的寫法,會(huì)默認(rèn)生成Object對(duì)象,因此要強(qiáng)制把constructor屬性指向Bar,執(zhí)行的過(guò)程是先看自身有沒(méi)有這個(gè)屬性,有就執(zhí)行,不管原型里是否還有,如果沒(méi)有就繼續(xù)查找原型,有就執(zhí)行,沒(méi)有就報(bào)錯(cuò),如何判斷是自身屬性還是原型里的屬性呢;
var bar = new Bar(); bar.name = "obama"; bar.hasOwnProperty("name"); //true //hasOwnProperty 只會(huì)判斷自身是否有這個(gè)屬性,原型是否有無(wú)法判斷; "name" in bar; //true // in這個(gè)方法更近一步能判斷不管自身還是原型有屬性(當(dāng)然是可以枚舉的屬性) //通過(guò)這兩個(gè)方法我們可以判斷原型中是否有屬性 function isProperty(object,property){ return !object.hasOwnProperty(property) && (property in object); }
重點(diǎn)!!原型是會(huì)重寫的,這和JS里其他的對(duì)象一樣,后面的會(huì)覆蓋前面的,還有個(gè)問(wèn)題是如果原型中修改屬性,一個(gè)實(shí)例對(duì)象就會(huì)改寫這個(gè)值,導(dǎo)致其他的實(shí)例對(duì)象都會(huì)改變?。?/p>
function Box(){ } Box.prototype = { constructor:Box, boxs:["box1","box2","box3"], name:"bigBox" } var box1 = new Box(); var box2 = new Box(); box1.name = "first box"; console.log(box1.name); //"first box" console.log(box2.name); //"bigbox" box1.boxs.push("box4"); console.log(box1.boxs); //["box1", "box2", "box3", "box4"] console.log(box2.boxs); //["box1", "box2", "box3", "box4"]
很難理解為什么box1修改name屬性就不會(huì)重寫原型,而修改boxs屬性就會(huì)重寫原型,兩者的差別就在于一個(gè)是賦值,一個(gè)是查找,打個(gè)比方,
a向b借了100元,那么a就得到了100元,不是a的父親,爺爺?shù)玫搅?00元,所以賦值即給a添加不論是屬性還是方法收益的只有a,不會(huì)給a的父親,爺爺其他人也賦值,但是如果b找a 還的話,如果找不到a就可以找a 的父親爺爺?shù)绕渌?,這個(gè)意思是是說(shuō),只要是賦值,就只作用在賦值對(duì)象上,但是查找就不同,可以一直追溯到其他人,上面的例子,
box1.boxs.push(""box4"),可以這么理解,首先是查找,box1.boxs,不然如何push呢,自身屬性沒(méi)有,但是原型上有,有就OK直接操作push,但是這個(gè)操作是對(duì)象是所有對(duì)象共享的,所以一旦修改就改變了!
基于以上的問(wèn)題,那么動(dòng)態(tài)原型模式就是把共享的使用原型,不共享的使用構(gòu)造函數(shù),
function Box(){ this.name:"bigBox"; this.boxs = ["box1", "box2", "box3"]; }; Box.prototype = { constructor:Box, num:function(){ console.log(this.boxs.length); } } //或者寫在一起 function Box(){ this.name:"bigBox", this.boxs = ["box1", "box2", "box3"]; if(typeof this.run != "function"){ Box.prototype.num = function(){ console.log(this.boxs.length); } } } //因?yàn)闃?gòu)造函數(shù)執(zhí)行時(shí),里面的代碼都會(huì)執(zhí)行一遍,而原型有一個(gè)就行,不用每次都重復(fù),所以僅在第一執(zhí)行時(shí)生成一個(gè)原型,后面執(zhí)行就不必在生成,所以就不會(huì)執(zhí)行if包裹的函數(shù), //其次為什么不能再使用字面量的寫法,我們都知道,使用構(gòu)造函數(shù)其實(shí)是把new出來(lái)的對(duì)象作用域綁定在構(gòu)造函數(shù)上,而字面量的寫法,會(huì)重新生成一個(gè)新對(duì)象,就切斷了兩者的聯(lián)系!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85111.html
摘要:可能因?yàn)橄热霝橹?,在編程之中,往往不由自主地以的邏輯編程思路設(shè)計(jì)模式進(jìn)行開發(fā)。這是原型模式很重要的一條原則。關(guān)于閉包與內(nèi)存泄露的問(wèn)題,請(qǐng)移步原型模式閉包與高階函數(shù)應(yīng)該可以說(shuō)是設(shè)計(jì)模式的基礎(chǔ)要領(lǐng)吧。在下一章,再分享一下的幾種常用設(shè)計(jì)模式。 前 在學(xué)習(xí)使用Javascript之前,我的程序猿生涯里面僅有接觸的編程語(yǔ)言是C#跟Java——忽略當(dāng)年在大學(xué)補(bǔ)考了N次的C與VB。 從靜態(tài)編程語(yǔ)言,...
摘要:將構(gòu)造函數(shù)的作用域賦值給新對(duì)象因此指向了新對(duì)象執(zhí)行構(gòu)造函數(shù)的代碼為這個(gè)新對(duì)象添加屬性返回對(duì)象最初是用來(lái)標(biāo)識(shí)對(duì)象類型的。但提到檢測(cè)對(duì)象類型,還是使用將構(gòu)造函數(shù)當(dāng)作函數(shù)構(gòu)造函數(shù)與其他函數(shù)唯一區(qū)別。 創(chuàng)建對(duì)象 雖然Object構(gòu)造函數(shù)與對(duì)象字面量都能創(chuàng)建單個(gè)對(duì)象, 但這些方式都有明顯的缺點(diǎn): 使用同一個(gè)接口創(chuàng)建很多對(duì)象, 會(huì)產(chǎn)生大量重復(fù)代碼。 var obj = {}; //對(duì)象字面量 va...
摘要:概括創(chuàng)建自定義類型的最常見方式,就是組合使用構(gòu)造函數(shù)模式與原型模式。應(yīng)用方式一分開定義,用來(lái)理解構(gòu)造函數(shù)與原型方式二動(dòng)態(tài)原型模式定義,避免獨(dú)立的構(gòu)造函數(shù)和原型,更完美的定義形式。 概括:創(chuàng)建自定義類型的最常見方式,就是組合使用構(gòu)造函數(shù)模式與原型模式。 好處:通過(guò)這種方式,不僅每個(gè)實(shí)例都有自己的一份實(shí)例屬性的副本,而且同時(shí)又共享著對(duì)方法的引用,最大限度的節(jié)省了內(nèi)存。而且這種混合模式還支...
摘要:組合使用構(gòu)造函數(shù)模式和原型模式創(chuàng)建自定義類型的最常見方式,就是組合使用構(gòu)造函數(shù)模式與原型模式。也就是說(shuō),寄生構(gòu)造函數(shù)模式下,構(gòu)造函數(shù)創(chuàng)建的對(duì)象與在構(gòu)造函數(shù)外創(chuàng)建的對(duì)象沒(méi)有什么不同。 前言 最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《JavaScri...
摘要:通過(guò)這種操作,就有了構(gòu)造函數(shù)的原型對(duì)象里的方法。你也看到了,就是一個(gè)普通對(duì)象,所以這種寄生式繼承適合于根據(jù)已有對(duì)象創(chuàng)建一個(gè)加強(qiáng)版的對(duì)象,在主要考慮通過(guò)已有對(duì)象來(lái)繼承而不是構(gòu)造函數(shù)的情況下,這種方式的確很方便。 原文地址在我的博客, 轉(zhuǎn)載請(qǐng)注明出處,謝謝! 標(biāo)簽: [es5對(duì)象、原型, 原型鏈, 繼承] 注意(這篇文章特別長(zhǎng))這篇文章僅僅是我個(gè)人對(duì)于JavaScript對(duì)象的理解,并不是...
閱讀 2515·2023-04-25 19:31
閱讀 2266·2021-11-04 16:11
閱讀 2819·2021-10-08 10:05
閱讀 1527·2021-09-30 09:48
閱讀 2327·2019-08-30 15:56
閱讀 2423·2019-08-30 15:56
閱讀 2184·2019-08-30 15:53
閱讀 2278·2019-08-30 15:44