摘要:上一篇面向對象版塊之理解對象下一篇面向對象版塊之定義多個對象屬性以及讀取屬性特性
這是 javascript 面向對象版塊的第二篇文章,主要講解的是對象的屬性,首先創建一個對象:
var person = { name: "Nicholas", age: 29, job: "Software Engineer", sayName: function () { console.log(this.name); } };
上面的例子創建了一個名為 person 的對象,并為它添加了三個屬性( name 、 age 和 job )和一個方法( sayName() )。其中, sayName() 方法用于顯示 this.name (將被解析為 person.name )的值。
ECMAScript 中有兩種屬性:數據屬性和訪問器屬性。
數據屬性是可獲取和設置值得屬性,數據屬性將 value 和 writable 屬性包含在其描述符中。數據屬性有4個描述其行為的特性:
[[Configurable]]:表示能否通過 delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為 true 。
[[Enumerable]]:表示能否通過 for-in 循環返回屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為 true 。
[[Writable]]: 表示能否修改屬性的值。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為 true 。
[[Value]]: 包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,把新值保存在這個位置。這個特性的默認值為 undefined 。
對于像前面例子中那樣直接在對象上定義的屬性,它們的 [[Configurable]] 、 [[Enumerable]]和 [[Writable]] 特性都被設置為 true ,而 [[Value]] 特性被設置為指定的值。例如:
var person = { name: "Nicholas", };
這里創建了一個名為 name 的屬性,為它指定的值是 "Nicholas" 。也就是說, [[Value]] 特性將被設置為 "Nicholas" ,而對這個值的任何修改都將反映在這個位置。
此時有這樣一個想法,如果我不允許修改 name 屬性的值,怎么辦?或者說我要修改屬性的默認特性,怎樣才可以實現呢?要實現這些功能就要用到 Object.defineProperty()方法,這個方法接收三個參數:屬性所在的對象、屬性的名字和一個描述符對象。其中,描述符(descriptor)對象的屬性必須是: configurable 、 enumerable 、 writable 和 value 。設置其中的一或多個值,可以修改對應的特性值。例如:
var person = {}; Object.defineProperty(person, "name", { writable: false, value: "Nicholas" }) console.log(person.name); // Nicholas person.name = "Greg"; console.log(person.name); // Nicholas
這個例子創建了一個 name 屬性,它的值 "Nicholas" 是只讀的。這個屬性不可修改,如果嘗試修改這個值的話在非嚴格模式下會被忽略,但是如果在嚴格模式下,會拋出錯誤:
Uncaught TypeError: Cannot assign to read only property "name" of object "#
var person = {}; Object.defineProperty(person, "name", { configurable: false, value: "Nicholas" }) console.log(person.name); // Nicholas delete person.name; console.log(person.name); // Nicholas
把 configurable 設置為 false ,表示不能從對象中刪除屬性。如果對這個屬性調用 delete ,則在非嚴格模式下什么也不會發生,而在嚴格模式下會導致錯誤。而且一旦把屬性定義為不可配置,就不能再把它變回可配置了。此時,再調用 Object.defineProperty() 方法修改特性,都會導致錯誤:
var person = {}; Object.defineProperty(person, "name", { configurable: false, value: "Nicholas" }) console.log(person.name); // Nicholas /* delete person.name; console.log(person.name); // Nicholas */ Object.defineProperty(person, "name", { writable: true })
也就是說 可以多次調用 Object.defineProperty() 方法修改同一屬性,但是當 configurable 設置為 false 后就不可以了。
在《JavaScript 高級程序設計(第三版)》中寫到:
“一旦把屬性定義為不可配置的,就不能再把它變回可配置了。此時,再調用 Object.defineProperty() 方法修改除 writable 之外的特性,都會導致錯誤。”
但是我試了一些,即使修改的是 writable 屬性,還是會報錯。如果我描述的有錯,還望各位大佬指出,以便交流。
在調用 Object.defineProperty() 來定義屬性時。如果不指定, configurable 、 enumerable 和writable 特性的默認值都是 false。其實在日常的開發中用到這種高級方法來定義屬性的機會還是比較少,不過理解這部分對理解對象還是有很大的好處。
訪問器屬性訪問器屬性不包含數據值,但包含一對兒 getter 和 setter 函數(不過,這兩個函數都不是必需的)。在讀取訪問器屬性的時候,會調用 getter 方法,這個函數復制返回有效的值;在寫入訪問器屬性的時候,會調用 setter 函數,這個函數復制如果修改數據。訪問器屬性有如下 4 個特性:
[[Configurable]] :表示能否通過 delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為數據屬性。對于直接在對象上定義的屬性,這個特性的默認值為true 。
[[Enumerable]] :表示能否通過 for-in 循環返回屬性。對于直接在對象上定義的屬性,這個特性的默認值為 true 。
[[Get]] :在讀取屬性時調用的函數。默認值為 undefined 。
[[Set]] :在寫入屬性時調用的函數。默認值為 undefined 。訪問器屬性不能直接定義,必須使用 Object.defineProperty() 來定義。請看下面的例子。
var book = { _year: 2004, edition: 1 } Object.defineProperty(book, "year", { get: function () { return this._year; }, set: function (newVal) { if (newVal > this._year) { this._year = newVal; return this.edition += newVal - 2004; } } }) book.year = 2005; console.log(book.edition); // 2
以上代碼代碼創建了一個 book 對象,定義了兩個屬性,_year 和 edition。而訪問器屬性 year 包含了一個 geter 函數和 setter 函數。getter 函數返回 _year 的值,而 setter 函數返正確的版本。當把 year 屬性修改成 2005 時,而 edition 變為 2,這是使用訪問器屬性的常見方式,即設置一個屬性的值會導致其他屬性發生變化。
不一定非要同時指定 getter 和 setter,如果只指定 getter ,表明該屬性不能寫,只能讀取,嘗試寫入屬性會被忽略,但在嚴格模式下會報錯。如果只指定 setter ,表明該屬性不能讀取,如果嘗試讀取,在嚴格模式和非嚴格模式下都會返回 undefined。
在《JavaScript 高級程序設計(第三版)》中寫到:小結
“只指定 setter 函數的屬性也不能讀,否則在非嚴格模式下會返回 undefined ,而在嚴格模式下會拋出錯誤。”
但在 chrome 中測試了一下,在嚴格模式下不會拋出錯誤,返回的也是 undefined 。如果我描述的有錯,還望各位大佬指出,以便交流。
本片博客主要介紹了兩種屬性:數據屬性和訪問器屬性,介紹了這兩種屬性的定義以及這兩種屬性的特性,主要使用方法 Object.defineProperty()。其實這篇文章主要是加強對對象的理解。
上一篇:javascript 面向對象版塊之理解對象
下一篇:javascript 面向對象版塊之定義多個對象屬性以及讀取屬性特性
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93176.html
摘要:用代碼可以這樣描述安全到達國外面向過程既然說了面向對象,那么與之對應的就是面向過程。小結在這篇文章中,介紹了什么是面向對象和面向過程,以及中對象的含義。 這是 javascript 面向對象版塊的第一篇文章,主要講解對面向對象思想的一個理解。先說說什么是對象,其實這個還真的不好說。我們可以把自己當成一個對象,或者過年的時候相親,找對象,那么你未來的老婆也是一個對象。我們就要一些屬性,比...
摘要:返回值是一個對象,如果是訪問器屬性,這個對象的屬性有和如果是數據屬性,這個對象的屬性有和。上一篇面向對象版塊之對象屬性下一篇面向對象版塊之創建對象 這是 javascript 面向對象版塊的第三篇文章,主要講解的是多個屬性的定義以及讀取屬性的特性。前面這幾章內容目的在于加深對對象的理解,這樣可以利于理解后面的原型鏈以及繼承方面的知識,或者你也可以了解一下不一樣的 javascript ...
摘要:一個不相關的總結鄙人現在寫代碼容易用一句話總結根本停不下來。這種狀況讓人生活狀態極差,黑夜白天顛倒,飽一頓餓一頓,體質下降,妹紙盡失我要遠離這種狀態。所以決定以后寫代碼盡可能只寫到點,要緊的話再趕趕,一般就停下來寫寫總結泡泡腳藍后碎覺。 1、OOP在粗粒度上面向對象,在細粒度上面向過程:即總體上看起來是一個模塊一個模塊的,細分起來還是需要一步一步執行的; 2、OOP提高了代碼重用效率,...
摘要:又將整個文藝類閱讀系統的業務劃分為兩大部分,分別是面向管理員和合作作者的后臺管理系統和面向用戶的移動端,系統的需求分析將圍繞這兩部分進行展開。 效果展示 showImg(https://user-gold-cdn.xitu.io/2018/8/26/16576a709bd02f5f?w=1409&h=521&f=gif&s=30128195); showImg(https://user...
摘要:又將整個文藝類閱讀系統的業務劃分為兩大部分,分別是面向管理員和合作作者的后臺管理系統和面向用戶的移動端,系統的需求分析將圍繞這兩部分進行展開。 效果展示 showImg(https://user-gold-cdn.xitu.io/2018/8/26/16576a709bd02f5f?w=1409&h=521&f=gif&s=30128195); showImg(https://user...
閱讀 1339·2021-11-11 16:54
閱讀 2385·2021-09-22 10:51
閱讀 2655·2019-08-30 15:44
閱讀 3206·2019-08-29 17:05
閱讀 1445·2019-08-29 17:01
閱讀 2900·2019-08-29 12:28
閱讀 2471·2019-08-26 13:50
閱讀 1731·2019-08-23 16:47