Object api

前言

昨天談到了這些問題,發現認識比較片面。決定仔細看看並總結一下。
研究Object的部分ES5 API。可能會提到部分ES6內容。es6

Object

Object MDN APIapi

屬性描述符

即描述對象屬性特性的描述符數組

四個特性描述符

  1. valuethis

  2. writable 只讀性spa

  3. enumerable 可枚舉性prototype

  4. configurable 可配置性(屬性的刪除與從新配置)指針

value默認爲undefined
在使用Object.create()Object.definePropertywritableenumerableconfigurable默認均爲falsecode

兩個訪問器

  1. get 不可與value同時使用,會由屬性的讀取觸發。對象

  2. set 不可與writable同時使用,會由屬性的寫入觸發。繼承

將會在其餘的api中介紹屬性描述符的用法

對象的建立與屬性修改

Object.create()

Object.create(proto, [ propertiesObject ])
此api的做用是以proto爲原型,以propertiesObject自有屬性(不包含propertiesObject的原型上的屬性,包含全部不可枚舉屬性)爲屬性建立一個新的對象。

// 非嚴格模式下運行,嚴格模式下會拋出異常
const proto = {
  saySize () {
    console.log(this.size)
  }
}
const propertiesObject = {
  size: {
    enumerable: false,
    configurable: false,
    value: 'large'
  },
  color: {
    writable: true,
    enumerable: true,
    configurable: true,
    value: 'red'
 }
}
let newObj = Object.create(proto, propertiesObject)

// 原型
newObj.saySize()
// "large"

// writable
newObj.size = 'small'
newObj.color = 'green'
console.log(newObj.size, newObj.color)
// "large,green"

// enumerbale
for(key in newObj){
  console.log(key)
}
// "color"
// "saySize"
delete newObj.size
// false
delete newObj.color
// true
  1. 上述代碼中的proto使用Fun.prototype便可實現原型鏈的繼承。

  2. 那麼要怎樣才能枚舉出enumerable:false的屬性呢?

Object.defineProperty()

Object.defineProperty(obj, prop, descriptor)
此api容許修改或向obj添加屬性
obj爲目標對象,prop爲要修改或添加的屬性,descriptor爲屬性描述符

let tempObj1 = {}
Object.defineProperty(tempObj, 'name', {
  value: 'temp',
  writable: false,
  enumerable: true,
  configurable: false
})
console.log(tempObj)
// Object {name: "temp"}

// 拋出異常
Object.defineProperty(tempObj, 'name', {
  value: temp,
  writable: true
})

對於configurable: false的屬性禁止修改屬性描述符,會拋出異常。

let tempObj2 = {_name: 'temp2'}
Object.defineProperty(tempObj2, 'name', {
  get () {
    return `名字爲${this._name}`
  },
  set (value) {
    console.log(`新名字爲${value}`)
  }
})
console.log(tempObj2.name)
// "名字爲temp2"
tempObj2.name = 'temp2.0'
// "新名字爲temp2.0"

能夠觀察到 讀屬性值與 寫屬性值分別觸發了getset屬性訪問器。
代碼中所用到的"`名字爲${this._name}`" 爲es6模板字符串,實現拼串

Object.defineProperties()

Object.defineProperties(obj, props)
此api方便了屬性的批量修改,第二個參數與Object.create()的第二個參數結構相同。

let tempObj3 = {name:'temp'}
Object.defineProperties(tempObj3, {
  name: {
    value: 'newTemp',
    writable: true
  },
  color: {
    value: 'red',
    writable: true,
    enumerable: true
  }
})
console.log(tempObj3)
// Object {name: "newTemp", color: "red"}

對象屬性的檢測與檢索

咱們也看到了對於enumerable:false的屬性是不可枚舉的。甚至ES6中還有「隱蔽性」更高的Symbol()能夠做爲屬性鍵。那麼怎麼才能正確的檢測與獲取對象的屬性呢?

咱們先建立一個對象用於實驗後續的全部方法。
原型和自身都各包含三種屬性:enumerable: false,enumerable: true,Symbol()

const proto = Object.create(null, {
  supTrue: {
    value: 'value1',
  enumerable: true
},
supFalse: {
  value: 'value2',
    enumerable: false
  }
})
proto[Symbol('supSymbol')] = 'supSymbol'
console.log(proto)
// {
//  supTrue: "value",
//  Symbol(supSymbol): "supSymbol",
//  supFalse: "value2"
// }
let obj = Object.create(proto, {
  ownTrue: {
    value: 'value1',
    enumerable: true
},
ownFalse: {
    value: 'value2',
    enumerable: false
  }
})
obj[Symbol('ownSymbol')] = 'ownSymbol'
// ok,obj可用

for-in

for (const key in obj) {
    console.log(key)
}
// subTrue, ownTrue

能夠看到for in枚舉了包括原型鏈在內的全部可枚舉屬性

Object.keys()

Object.keys(obj)
// ["ownTrue"]

能夠看到返回了一個只包含自身可枚舉屬性鍵的數組。

Object.getOwnPropertyNames()

Object.getOwnPropertyNames(obj)
// ["ownTrue", "ownFalse"]

能夠看到返回了一個包含自身全部非symbol的屬性鍵的數組。
由此也能夠看到symbol類型的屬性的「隱蔽性」

Object.getOwnPropertySymbols()

針對 獲取symbol可以使用此方法。

Reflect.ownKeys()

雖然這個不是Object的方法
可是能夠用來獲取自身全部屬性鍵

Reflect.ownKeys(obj)
// ["ownTrue", "ownFalse", Symbol(ownSymbol)]

把對象關起來

按照權限從大到小排列

Object.preventExtensions()

做用:將對象變的不可擴展,不可添加新的屬性。

Object.seal()

做用:將對象「密封」,不可添加新屬性,屬性的configurable置爲falsewritabletrue的屬性仍然能夠被從新賦值。
權限:僅可對writabletrue的屬性進行賦值。

Object.freeze()

做用:徹底「鎖死」,不能作任何修改。
權限:0。

須要注意的是,上述三個api都是對原有對象的操做,並不會返回一個新的對象。

let obj = {}
Object.preventExtensions(obj) === obj // true
Object.seal(obj) === obj // true
Object.freeze(obj) === obj // true

能夠說writable,configurable這些屬性描述符是針對對象的屬性作出的限制或者保護。
那麼Object.seal(),Object.preventExtensions(),Object.freeze()就是對對象自己作出限制或者保護。
同時咱們也知道在ES6中使用const能夠聲明一個"常量",可是要注意的是const確保的只是指針的不可更改。好比:

const obj = {key: 'value1'}
obj.key = 'value2' // 可完成
obj = {key2: 'value2'} // 更改指針,拋出異常

針對對象,此時就能夠使用上述三個把對象關起來的api。

相關文章
相關標籤/搜索