摘要:今天結(jié)合高編第六章開始回顧和深入學(xué)習(xí)面向?qū)ο蟛糠职▽?duì)象原型原型鏈繼承等部分。二對(duì)象的屬性類型勾鑫宇,數(shù)據(jù)屬性訪問器屬性書上講到屬性類型時(shí),只是簡(jiǎn)單提了一下是為了表示對(duì)象的特性,描述了屬性的特征,并且在中不能直接訪問。
前言
JavaScript發(fā)明之始,從技術(shù)上來(lái)講就是一門面向?qū)ο蟮恼Z(yǔ)言,但在ES6之前,JS的很多特性和傳統(tǒng)的面向?qū)ο笳Z(yǔ)言有所不同,比如沒有類的概念(ES6有了class)。今天結(jié)合《JS高編》第六章開始回顧和深入學(xué)習(xí)面向?qū)ο蟛糠?包括對(duì)象、原型、原型鏈、繼承等部分。
一、理解對(duì)象談JS的對(duì)象之前,先復(fù)習(xí)一下面向?qū)ο蟮幕A(chǔ)概念和特點(diǎn)吧。
面向?qū)ο驩OP(Object-oriented programming),結(jié)合維基百科和百度百科的闡述,再談?wù)勎业睦斫狻?/p>
官方解釋:
面向?qū)ο缶褪腔趯?duì)象概念,以對(duì)象為中心,以類和繼承為構(gòu)造機(jī)制,來(lái)認(rèn)識(shí)、理解、刻畫客觀世界和設(shè)計(jì)、構(gòu)建相應(yīng)的軟件系統(tǒng)
我的理解:
在JavaScript的世界中,萬(wàn)物皆對(duì)象。任何事和物你都可以將其定義為一個(gè)對(duì)象,程序員界有個(gè)笑話就是單身狗可以new一個(gè)對(duì)象嘛......我的粗淺理解,如果我是一個(gè)上帝,這個(gè)世界的任何人和事相對(duì)于我而言都是一個(gè)對(duì)象。有了控制對(duì)象的權(quán)力,我就可以對(duì)他們進(jìn)行任何操作。針對(duì)事,我可以發(fā)布一個(gè)號(hào)令,發(fā)布一個(gè)政策,告訴別人怎么執(zhí)行,什么時(shí)候開始,什么時(shí)候結(jié)束。針對(duì)人,我可以把他們分為男人、女人,這就是類。然后我可以限制他們的兒子是男人還是女人,是男人那就必須有和爸爸一樣的性別特征,這就是繼承。我還可以控制他們什么時(shí)間做什么事等等,整個(gè)過(guò)程我都是圍繞某個(gè)對(duì)象來(lái)展開的,那么這個(gè)過(guò)程叫做面向?qū)ο蟆?/p>
特點(diǎn):
1.類
2.繼承
3.封裝
4.多態(tài)
具體的在后面學(xué)習(xí)和復(fù)習(xí)時(shí)再談。
let obj = { name:"勾鑫宇", age:23 }
1.數(shù)據(jù)屬性:[[Configurable]],[[Enumerable]],[[Writable]],[[Value]]
2.訪問器屬性:[[Configurable]],[[Enumerable]],[[Get]],[[Set]]
書上講到屬性類型時(shí),只是簡(jiǎn)單提了一下是為了表示對(duì)象的特性,描述了屬性的特征,并且在JS中不能直接訪問。光看介紹不太理解到底是干什么的,但是看了數(shù)據(jù)屬性的內(nèi)容之后,發(fā)現(xiàn)不難理解。
我的理解,數(shù)據(jù)屬性就是我們可以從根源去控制一個(gè)對(duì)象的屬性是否能被修改、刪除、循環(huán)等,并可以通過(guò)訪問器屬性在別人不知道的情況下進(jìn)行數(shù)據(jù)處理。通過(guò)Object.defineProperty()這個(gè)方法,我們可以去設(shè)置這些限制對(duì)象屬性操作的值,從而限制別人對(duì)某個(gè)對(duì)象屬性的操作。舉個(gè)例子,上面的obj這個(gè)對(duì)象的name屬性的值是“勾鑫宇”,從現(xiàn)在起我不想任何人能夠修改它的值,那么我就通過(guò)數(shù)據(jù)屬性來(lái)將這個(gè)屬性設(shè)置為不可修改,別人用obj.name = "張三"來(lái)修改就不會(huì)生效了。而我如果想在修改name屬性的值后同時(shí)讓age也跟著改變,那么此時(shí)就可以用訪問器屬性來(lái)進(jìn)行數(shù)據(jù)處理。
我們是通過(guò)Object.defineProperty()這個(gè)方法來(lái)進(jìn)行兩種屬性的設(shè)置。那么首先了解一下Object.defineProperty()這個(gè)方法,它接收三個(gè)參數(shù):
Object.defineProperty(對(duì)象名,屬性名,描述符對(duì)象) //舉例 Object.defineProperty(obj,"name",{ writable:false,//設(shè)置不可修改 enumerable:false//設(shè)置不可循環(huán)到該屬性 })
可以在對(duì)象的constructor中找到該方法
同時(shí),我們可以通過(guò)Object.getOwnPropertyDescriptor()方法來(lái)查看這四個(gè)特性的設(shè)置情況。接受兩個(gè)參數(shù):
Object.getOwnPropertyDescriptor(對(duì)象名,屬性名)數(shù)據(jù)屬性
數(shù)據(jù)屬性包含一個(gè)數(shù)據(jù)值的位置。在這個(gè)位置可以讀取和寫入值,有4個(gè)描述其行為的特性。
下面就具體來(lái)對(duì)每個(gè)數(shù)據(jù)屬性進(jìn)行分析:
1.[[Writable]]:英文意思譯為“可寫的”,可理解為“可修改的”。這個(gè)屬性用來(lái)設(shè)置對(duì)象的某個(gè)屬性是否能被修改,默認(rèn)為true。
//舉例 let obj = { name:"勾鑫宇", age:23 } Object.defineProperty(obj,"name",{ writable:false,//設(shè)置不可修改 }) //這時(shí)再進(jìn)行修改就不會(huì)生效,嚴(yán)格模式下會(huì)報(bào)錯(cuò) obj.name = "張三" console.log(obj.name)//輸出的還是勾鑫宇
嚴(yán)格模式報(bào)錯(cuò)
2.[[Enumerable]]:英文譯為“可數(shù)的,可枚舉的”,是否支持for-in循環(huán)來(lái)返回屬性,默認(rèn)為true。
//舉例 let obj = { name:"勾鑫宇", age:23, gender:male } Object.defineProperty(obj,"name",{ enumerable:false,//設(shè)置不可通過(guò)for-in循環(huán)返回 }) //循環(huán)測(cè)試 for(let i in obj){ console.log(i)//輸出結(jié)果為age,gender,沒有name屬性,效果就像隱藏了這個(gè)屬性。 } //但這時(shí)我們的name屬性還是存在的 console.log(obj)
3.[[value]]:這個(gè)就不說(shuō)翻譯了,大家都知道,就是值。這個(gè)特性是設(shè)置我們對(duì)象某個(gè)屬性的值,讀值、寫值都在這里,默認(rèn)值為undefined。
//舉例 let obj = { name:"勾鑫宇", age:23, gender:male } Object.defineProperty(obj,"name",{ value:"張三",//設(shè)置name的值為張三 }) console.log(obj.name)//輸出為張三 //設(shè)置value不影響后面再次修改值,value相當(dāng)于修改了一次你最先定義的值而已。 obj.name = "傻逼" concole.log(obj.name)//輸出為“傻逼”
4.[[Configurable]]:英文譯為“可配置的”,這個(gè)和前面的Writable有什么區(qū)別呢?放到最后講是有原因的。前面有設(shè)置修改,設(shè)置循環(huán),設(shè)置值,但是還沒有設(shè)置是否可刪除。Configurable就是做這個(gè)事情的。它表示能否通過(guò)delete刪除屬性從而重新定義屬性,默認(rèn)值為true。
//舉例 let obj = { name:"勾鑫宇", age:23, gender:male } Object.defineProperty(obj,"name",{ configurable:false,//不允許刪除屬性 }) delete obj.name//報(bào)錯(cuò)"Uncaught TypeError: Cannot delete property "name" of #
這個(gè)屬性還有最重要的一個(gè)特點(diǎn),就是當(dāng)你設(shè)置為false過(guò)后,就不能再設(shè)為true了,即使你設(shè)置了也無(wú)效。書上說(shuō)得個(gè)時(shí)候你再設(shè)置value,enumerable都不會(huì)生效,只能設(shè)置writable,那么我們來(lái)試試。
//接著上面再把configurable修改為true Object.defineProperty(obj,"name",{ configurable:true, }) //此時(shí)為會(huì)報(bào)錯(cuò)“Uncaught TypeError: Cannot redefine property: name” //接著再次調(diào)用 Object.defineProperty(obj,"name",{ value:"張三" }) console.log(obj)//此時(shí)打印出來(lái)的是“張三”,而并書上所說(shuō)的不能修改value的值。 //設(shè)置enumerable Object.defineProperty(obj,"name",{ enumerable:false//報(bào)錯(cuò)"Uncaught TypeError: Cannot redefine property: name" })
測(cè)試了很多遍,value值在configurable為false的情況下仍然是可以修改的。
//設(shè)置writable Object.defineProperty(obj,"name",{ writable:false//不會(huì)報(bào)錯(cuò) }) //再次修改writable Object.defineProperty(obj,"name",{ writable:true//報(bào)錯(cuò)“Uncaught TypeError: Cannot redefine property: name” }) //修改value Object.defineProperty(obj,"name",{ value:"張三"http://報(bào)錯(cuò)“Uncaught TypeError: Cannot redefine property: name” })
上面設(shè)置writable說(shuō)明在configurable和writable同時(shí)為false的情況下,就不能再修改任何值了。
Configurable還能控制是否能修改為訪問器屬性,這個(gè)在訪問器屬性的時(shí)候再講。
訪問器屬性不包含數(shù)據(jù)值,包含一對(duì)getter和setter函數(shù),讀取訪問器屬性時(shí)調(diào)用getter,寫入時(shí)調(diào)用setter,并負(fù)責(zé)處理數(shù)據(jù)。
訪問器屬性同樣有4個(gè)特性值可以設(shè)置:
1.[[Configurable]]:和數(shù)據(jù)屬性的功能一樣,只是有一點(diǎn)區(qū)別就是能否修改為數(shù)據(jù)屬性。
2.[[Enumerable]]:和數(shù)據(jù)屬性的功能一樣。
3.[[Get]]:讀取屬性時(shí)調(diào)用,默認(rèn)值為undefined。
get函數(shù)就是能夠讓你讀取對(duì)象中的某個(gè)屬性,前提是這個(gè)屬性本身是只能通過(guò)對(duì)象方法來(lái)訪問的,也就是說(shuō)定義時(shí)要有下劃線記號(hào),否則本身就能直接訪問的話,用get也沒有意義了。
//舉例 let obj = { _name:"勾鑫宇",//下劃線是一種記號(hào),表示只能通過(guò)對(duì)象方法訪問 age:23, gender:male } console.log(obj.name)//輸出為undefined //用get方法來(lái)讀取這個(gè)屬性,并返回給對(duì)象 Object.defineProperty(obj,"name",{ get(){ return this._name } }) console.log(obj.name)//輸出“勾鑫宇”
4.[[Set]]:set函數(shù)就是寫入屬性的時(shí)候調(diào)用,默認(rèn)值為undefined。
set函數(shù)會(huì)接收一個(gè)參數(shù),這個(gè)參數(shù)就是我們修改對(duì)象或添加對(duì)象的屬性值。
//舉例 let obj = { _name:"勾鑫宇", age:23, gender:male } //用set方法來(lái)寫入這個(gè)屬性 Object.defineProperty(obj,"name",{ set(val){ this._name = "hh"+val } }) obj.name = "張三" console.log(obj.name)//輸出為undefined
這個(gè)時(shí)候我們就沒法進(jìn)行下去了,因?yàn)闊o(wú)論怎樣,都是輸出undefined。原因就是因?yàn)槲覀儧]有使用get函數(shù)去讀取我們寫入的屬性值,記住name在初始定義時(shí)就必須是_name。
//同時(shí)使用get和set let obj = { _name:"勾鑫宇", age:23, gender:male } //用set方法來(lái)寫入這個(gè)屬性 Object.defineProperty(obj,"name",{ get(){ return this._name }, set(val){ this. = "hh"+val } }) obj.name = "張三" console.log(obj.name)//輸出"hh張三"
從上面的代碼就可以看出這個(gè)set和get函數(shù)的強(qiáng)大之處,那就是可以進(jìn)行數(shù)據(jù)處理。我們可以通過(guò)set函數(shù)來(lái)進(jìn)行對(duì)象里不同屬性的關(guān)聯(lián),也可以實(shí)現(xiàn)屬性值的各種計(jì)算。
//舉例 let obj = { _name:"勾鑫宇", age:23, gender:male } //用set方法來(lái)進(jìn)行不同屬性間的關(guān)聯(lián) Object.defineProperty(obj,"name",{ get(){ return this._name }, set(val){ if(val === "張三"){ this._name = val; this.age = 18 } } }) //修改屬性值 obj.name = "張三"; console.log(obj)//輸出 {name:"張三",age:18,gender:male}
除了Object.defineProperty()方法,還有Object.defineProperties()方法,顧名思義,復(fù)數(shù)形式就是可以同時(shí)定義多個(gè)屬性。它接受兩個(gè)參數(shù):
Object.defineProperties(obj,{ name:{ writable:false }, age:{ configurable:true } ... })
這就是對(duì)屬性類型的一個(gè)學(xué)習(xí)和理解,如有錯(cuò)誤,請(qǐng)使勁點(diǎn)我。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/103943.html
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過(guò)對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來(lái)。注意中,對(duì)象一定是通過(guò)類的實(shí)例化來(lái)的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:官方解釋工廠是構(gòu)造方法的抽象,抽象了創(chuàng)建具體對(duì)象的過(guò)程。工廠方法模式的實(shí)質(zhì)是定義一個(gè)創(chuàng)建對(duì)象的接口,但讓實(shí)現(xiàn)這個(gè)接口的類來(lái)決定實(shí)例化哪個(gè)類。 前言 上一章回顧了JS對(duì)象的屬性類型,那么除了我們常用的new Object()構(gòu)造函數(shù)創(chuàng)建對(duì)象和字面量方式創(chuàng)建對(duì)象的方式外,還需要用到更多的模式來(lái)解決對(duì)象被多次復(fù)用的問題。什么意思呢?就是我們很有可能會(huì)在各個(gè)地方去使用已經(jīng)創(chuàng)建過(guò)的對(duì)象,但是對(duì)象...
摘要:請(qǐng)記住,這些書中的一些可能不是最新的,但概念和基礎(chǔ)仍應(yīng)適用。是最好的老師之一。的秘密由部分組成。在你完成這些書后,查看書籍和最好的本土?xí)? 我看過(guò)三本,第1本,第二本,第四本。第一本買的的實(shí)體書,其他兩本看的是電子書。第一本是大名鼎鼎老道寫的,書很薄,但是非常經(jīng)典。javascirpt忍者秘籍是jquery的作者寫的,也是非常經(jīng)典。you dont kown js系列也是非常好??戳?..
閱讀 1256·2021-09-27 13:34
閱讀 1070·2021-09-13 10:25
閱讀 567·2019-08-30 15:52
閱讀 3510·2019-08-30 13:48
閱讀 736·2019-08-30 11:07
閱讀 2228·2019-08-29 16:23
閱讀 2054·2019-08-29 13:51
閱讀 2390·2019-08-26 17:42