理解物件和物件的描述特性
阿新 • • 發佈:2018-11-03
JavaScript面向物件OOM 1(理解物件和物件的描述特性)
Date: Updated At Oct 31, 2018 | JavaScript | 面向物件 | Author: ZhengAo |
- 面向物件的語言都有一個特性 -- 都有類的概念。通過類可以建立一系列屬性相近,功能類似的物件。
- JavaScript 中沒有類的概念,JS 有特殊的面向物件的技巧--通過原型的方式。每個物件都是基於一個引用型別建立的
- 首先要對 Js 的物件有一個簡單的認識。Js 中的物件就是一個 Key-Value 對組成的集合。
- 其中 Value 可以是一個基礎資料型別,也可以是一個引用資料型別。
- Key 可以是一個任意可以轉換成字串的型別(Js 內部會自動把 Key 都轉換成字串,也可以理解成 Key 是一個字串)
I-1 建立物件
- 建立一個物件最開始(基本、沒人用)的方式就是建立一個 Object 的例項。
- 建立之後為其新增屬性。
<!--建立例項--> var person = new Object(); <!--新增屬性--> person.name = 'Zhang San'; person.talk = function() { console.log('name', this.name); }
- 在之後最常使用的就是通過物件字面量的方式建立一個新物件。
<!--字面量-->
var person = {
name: 'Zhang San',
talk: function() {
console.log('name', this.name);
}
- 使用物件字面量建立理論上可以減少記憶體的使用,提高效能,更高效(減少了建立例項時候的 prototype 的呼叫,縮短原型鏈)。開發體驗上字面量的方式更好。
- 參考: 使用字面量建立的好處
I-2 物件的屬性
- 首先要明白,Js 中的物件的屬性分為兩種: 資料屬性和訪問器屬性
- Js 的屬性中有一些是使用雙中括號括起來的例如:
[[Configurable]]
,這些屬性是 JS 引擎所訪問的。
I-2-1 資料屬性
- 資料屬性包含一個數據值的位置,可以讀取和寫入。 這個位置指的是在物件中有一個可以看到的屬性
var obj = {
demo : 123
}
上面的 demo
就是一個數據屬性
資料屬性中有4個描述它的特性(注意區分大小寫,使用的時候是小寫開頭)
- [[Configurable]]翻譯:可配置的 可以從新定義的屬性。預設值: true。
- [[Enumerable]]翻譯:可列舉的 可以遍歷的屬性(for-in) 預設值:true
- [[Writable]]翻譯:可寫的 可以修改屬性的值。 預設值: true
- [[Value]]屬性Key對應的值。讀取的時候從這裡讀取。預設值是undefined
使用物件字面量的方式為物件新增的屬性,其[[Configurable]]
`[[Enumerable]]`[[Writable]]
的值是true,[[Value]的值是指定的值。
在初始化物件之後,我們會有修改它的慾望,Js 在(ES5)的時候為我們提供了一個方法用於修改這些描述特性。
- 修改物件屬性(A.x)的資料屬性時候,使用:
Object.defineProperty(物件,物件的屬性,描述符物件)
方法。 -
函式名比較長,理解語義記憶:
- Object: 首先這是一個物件預設的方法。
- define(定義)
- property(特性)
- 小駝峰寫法寫成: Object.defineProperty()
<!--定義一個物件-->
var person = {};
<!--建立一個屬性-->
Object.defineProperty(person, name, {
writable: false,
value: 'Zhang San'
})
console.log(person.name) // Zhang San
<!--由於設定了屬性特性 writable = false 所以不可以更改-->
person.name = 'Li Si'
console.log(person.name) // Zhang San
- 在多次呼叫
Object.defineProperty()
方法修改一個屬性的configurable
的值的時候,一旦設定了false
就不可以再次修改。 - 這個方法的最小相容為 IE9+ ,其他現代瀏覽器基本都可以提供這個方法(不相容建議放棄或強制升級)。
I-2-2訪問器屬性
- 什麼是訪問器屬性:先看一個例子
var book = {
_year: 2005,
edition: 1,
}
// 注意這裡的 year 不是 _year, year就是一個訪問器屬性,_year是一個數據屬性。
Object.defineProperty(book, 'year', {
get: function() { return this._year },
set: function(newVal) {
this.editor += newVal - 2004 ;
this._year = newVal;
}
})
-
通過例子可以看出訪問器屬性和資料屬性非常大的區別就是
- 訪問器屬性不包含具體的數值,不直接顯示在物件中,不能直接通過字面量定義。
- 訪問器屬性有 get 和 set 方法才能為其賦值。
- 訪問器屬性的定義經常會引起其他資料屬性的變化。(這就是它的一個重要作用)
- 至於例子中的
_year
的寫法:有的時候<span style="color: red">明確的程式碼風格</span>可以更好的表現程式碼的功能。比如在物件的屬性中使用_year
代表這個屬性 <u >只有通過物件內部呼叫訪問</u> 。 - 定義一個訪問器屬性,必須使用 Object.defineProperty()這個方法定義
-
訪問器屬性提供了4個描述特性。
- [[Configurable]] 同資料屬性
- [[Enumerable]] 同資料屬性
- [[Get]] 讀取的時候呼叫函式。預設值為:undefined
- [[Set]] 設定的時候呼叫函式。預設值為:undefined
- get和set 不一定同時存在,存在一個表明:操作另一個的時候不會得到結果,嚴格模式會報錯。
- 相容性: IE9+
I-3 操作物件的多個屬性
- 以上兩節主要說明了單個屬性描述特性的操作,批量的屬性操作可以提升語義和簡化程式碼。
- JS 提供了可以一次性定義多個屬性的方法:使用
Object.defineProperties(物件,描述物件)
方法
var book = {};
Object.defineProperties(book, {
_year: {
value: 2004
},
edition: {
value: 1
},
year: {
get: function(){
return this._year;
},
set: function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
I-4 讀取物件的屬性特性
- Js 提供了
Object.getOwnPropertyDescriptor(物件,屬性)
的方法獲取指定物件的特定屬性的描述特性。 -
方法名記憶: 物件方法.獲取-自身的特性-描述符特性
-
get
:獲取 -
own
:自身的 -
property
:特性 -
descriptor
:描述特性 - 使用小駝峰連結:
getOwnPropertyDescriptor()
-
- 未特殊指定的描述特性,它的值是預設值。
- 相容性 IE9+
參考資料
- 《JavaScript高程》