理解對象和對象的描述特性

JavaScript面向對象OOM 1(理解對象和對象的描述特性)

Date: Updated At Oct 31, 2018 | JavaScript | 面向對象 | Author: ZhengAo |

  1. 面向對象的語言都有一個特性 -- 都有類的概念。通過類可以創建一系列屬性相近,功能類似的對象。
  2. 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 對象的屬性

  1. 首先要明白,Js 中的對象的屬性分爲兩種: 數據屬性和訪問器屬性
  2. 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高程》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章