對象(讀書筆記)

對象屬性的四大特性

對象的屬性除了包含名字和值以外,屬性還包含了寫標識它們可寫,可枚舉和可配置的特性es6

ES5後,對於屬性的三大特性,js提供對應的API。經過這些API給原型對象添加方法,並將它們設置成不可枚舉的,這讓它們看上去更像內置方法。api

能夠經過這些api給對象定義不能修改或刪除的屬性,藉此封鎖這個對象。數組

數據屬性的4個特性分別是:bash

1.值(value)函數

2.可寫性(writable)ui

3.可枚舉性(enumerable)spa

4.可配置性(configurable)prototype

存取器屬性的4個特性code

1.讀取(get)對象

2.寫入(set)

3.可枚舉性(enumerable)

4.可配置性(configurable)

ES5定義了一個對象名爲「屬性描述符」(property descriptor)來表明對象屬性的特性。數據屬性的描述符對象的屬性有value,writable,enumerable , configurable,存取器屬性的描述符對象則用get和set屬性代替value和writable。其中enumerable,configurable,writable是布爾值,set和get屬性是函數值。

經過調用Object.getOwnPropertyDescriptior()能夠得到某個對象特定屬性的屬性描述符。該API只能獲得自由屬性的描述符。要想得到對象集成對象屬性的特性,須要遍歷原型鏈(Object.getPrototypeOf()).若想設置屬性的特性或者想讓新建的屬性具備某種特性,則須要調用Object.defineProperty()

Object.defineProperty(O,"x",{
                value:1, writable:true, enumerable:false, configurable:true
      })
複製代碼

屬性的可枚舉性和遍歷 

可枚舉性

對象的每一個屬性都有一個描述對象(Descriptor),用來控制該屬性的行爲。Object.getOwnPropertyDescriptor方法能夠獲取該屬性的描述對象。

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }
複製代碼

描述對象的enumerable屬性,稱爲」可枚舉性「,若是該屬性爲false,就表示某些操做會忽略當前屬性。

目前,有四個操做會忽略enumerablefalse的屬性。

  • for...in循環:只遍歷對象自身的和繼承的可枚舉的屬性。
  • Object.keys():返回對象自身的全部可枚舉的屬性的鍵名。
  • JSON.stringify():只串行化對象自身的可枚舉的屬性。
  • Object.assign(): 忽略enumerablefalse的屬性,只拷貝對象自身的可枚舉的屬性。

這四個操做之中,前三個是 ES5 就有的,最後一個Object.assign()是 ES6 新增的。其中,只有for...in會返回繼承的屬性,其餘三個方法都會忽略繼承的屬性,只處理對象自身的屬性。實際上,引入「可枚舉」(enumerable)這個概念的最初目的,就是讓某些屬性能夠規避掉for...in操做,否則全部內部屬性和方法都會被遍歷到。好比,對象原型的toString方法,以及數組的length屬性,就經過「可枚舉性」,從而避免被for...in遍歷到。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false

Object.getOwnPropertyDescriptor([], 'length').enumerable
// false
複製代碼

上面代碼中,toStringlength屬性的enumerable都是false,所以for...in不會遍歷到這兩個繼承自原型的屬性。

另外,ES6 規定,全部 Class 的原型的方法都是不可枚舉的。

Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable
// false
複製代碼

總的來講,操做中引入繼承的屬性會讓問題複雜化,大多數時候,咱們只關心對象自身的屬性。因此,儘可能不要用for...in循環,而用Object.keys()代替。

相關文章
相關標籤/搜索