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