面向对象--内部属性类型
js中的對象有一些內部才用的特性,這些特性是為了實現javascript引擎用的,因此在javascript中不能直接訪問它們。
有兩種屬性:數據屬性 && 訪問器屬性
數據屬性
- [[ configurable ]]: 表示能否通過 delete 刪除屬性然后重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。直接在對象上定義的屬性,它們這個特性的默認值為 true;
- [[ enumerable ]]: 表示能否通過 for-in 循環返回屬性。直接在對象上定義的屬性,它們這個特性的默認值為 true;
- [[ writable ]]: 表示能否修改屬性的值。直接在對象上定義的屬性,它們這個特性的默認值為 true;
- [[ value ]]: 包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性的時候,把新值保存在這個位置。這個特性的默認值為 undefined ;
要修改屬性的特性,必須使用 ES5 的 Object.definePrototype() 方法。這個方法接受三個參數:
1、屬性所在的對象。
2、屬性的名字。
3、描述符對象。屬性必須是:configurable、enumerable、writable、value中的一個或多個。
var obj = {}; Object.defineProperty(obj, 'name', {writable: false, // 不能修改值value: '張三' }) console.log(obj.name); // 張三 obj.name = '李四'; console.log(obj.name); // 張三, writable設為 false 后,值就沒法修改了。 var person = {name: '李四',age: 24 } delete person.name; console.log(person); // {age: 24} Object.defineProperty(person, 'age', {configurable: false }) delete person.age; console.log(person);// {age: 24} configurable特性設為 false 后,就沒法使用 delete 刪除了。 復制代碼把 configurable 設置為 false 后,就不能用 delete 刪除屬性,而且,也不能修改 除 writable 外的特性。
var obj = {}; Object.defineProperty(obj, "name", {configurable: false,value: '張三' })// 會拋出錯誤 Object.defineProperty(obj, "name", {configurable: true,value: '張三' }) 復制代碼也就是說,可以多次調用 Object.defineProperty()方法修改同一個屬性,但在把 configurable特性設置為 false 后就有限制了。在調用Object.defineProperty()方法創建一個新的屬性時,如果不指定,configurable、enumerable、writable 特性的默認值都是 false,如果是修改已存在的屬性,就不會有這個限制。
訪問器屬性
訪問器屬性沒有數據值,有get、 set函數。讀取訪問器屬性時,會調用 get函數,在寫入值時會調用set函數。
訪問器屬性有如下四個特性:
- [[ configurable ]]: 表示能否通過 delete 刪除屬性,從而重新定義屬性。能否修改屬性的特性,或者能否把屬性修改為數據屬性。直接在對象上定義的屬性,它們這個特性的默認值為 true;
- [[ enumerable ]]: 表示能否通過 for-in 循環返回屬性。直接在對象上定義的屬性,它們這個特性的默認值為 true;
- [[ get ]]: 讀取屬性時,調用的函數。默認值為 undefined;
- [[ set ]]: 寫入屬性時,調用的函數。默認值為 undefined;
訪問器屬性不能直接定義,必須通過Object.defintProperty()來定義。
let person = {name: '張三',age: 25 } Object.defineProperty(person, 'oldAge', {get: function () {return this.age + 1;},set: function (newValue) {if (newValue > this.age) {this.age = newValue - 1;this.name = '李四'} else {this.age = newValue + 1;this.name = "王五"}} })person.oldAge = 28; console.log(person); // {name: '李四', age: 27}; 復制代碼上面定義了一個 person 對象。默認有兩個屬性, "name"、"age"。新增了一個訪問器屬性 "oldAge"。它包含了兩個函數。 get 函數用來返回值。set函數,當為 "oldAge"寫入值的時候,會調用。把 oldAge 設置為 27 后,調用 set 函數,改變了 person 對象的 "name" 和 "age" 屬性值。
不一定非要同時指定 set、get函數。只指定 get函數,意味著屬性不能寫,嚴格模式會報錯。只指定了set函數,屬性就不能讀取,嚴格模式同樣會報錯。
定義多個屬性
ES5 定義了一個 Object.defineProperties() 方法,可以通過描述符一次定義多個屬性。這個方法,接受兩個對象參數:第一個是要添加和修改其屬性的對象,第二個就是要設置的屬性的對象。
let car = {}; Object.defineProperties(car, {createYear: {writable: false,value: 2010},color: {writable: true,value: 'block'},severalYear: {get: function () {return parseInt(new Date().getFullYear()) - this.createYear},set: function (newValue) {if (newValue > 2010) {this.color = 'red';}} } }) console.log(car.createYear); // 2010 console.log(car.color); // 'block' console.log(car.severalYear); // 8 car.severalYear = 2015; console.log(car.createYear); // 2010 console.log(car.color); // 'red' console.log(car.severalYear); // 8 復制代碼需要注意的是:雖然我們設置 car.severalYear = 2015. 但是car.severalYear的值并沒有改變。因為為訪問器屬性寫入值的時候,只是會去執行 set 函數,而真實的值只能是通過get函數返回。
讀取屬性的特性
使用 ES5 的 Object.getOwnPropertyDescriptor()方法,可以取得給定屬性的描述符。這個方法接受兩個參數:
1、屬性所在的對象。
2、屬性名稱。
返回值是一個對象,如果是數據屬性,這個對象的屬性有:configurable、enumerable、writable、value。 如果是一個訪問器屬性,對象的屬性有:configurable、enumerable、get、set。
let car = {}; Object.defineProperties(car, {createYear: {writable: false,value: 2010},color: {writable: true,value: 'block'},severalYear: {get: function () {return parseInt(new Date().getFullYear()) - this.createYear},set: function (newValue) {if (newValue > 2010) {this.color = 'red';}} } })let descriptpor = Object.getOwnPropertyDescriptor(car, "createYear"); console.log(descriptpor); // { value: 2010, // writable: false, // enumerable: false, // configurable: false }let fangdescriptpor = Object.getOwnPropertyDescriptor(car, "severalYear"); console.log(fangdescriptpor); // 看下圖 復制代碼在 JavaScript 中可以針對任何對象-----包括 DOM 和 BOM 對象使用 Object.getOwnPropertyDescriptor()方法。
轉載于:https://juejin.im/post/5abce33e6fb9a028cf328eb2
總結
以上是生活随笔為你收集整理的面向对象--内部属性类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 内部类示例
- 下一篇: 1968. [AHOI2005]约数研究