ES5 數據屬性描述符和存取描述符

1、數據屬性描述符

對象是一個屬性集合,對象的基本特徵是屬性名(name)和屬性值(value)。ES5 增長了屬性描述符,能夠更細膩的控制屬性的不一樣操做。屬性描述符有 configurable、writable 和 enumerable。javascript

屬性描述符一般和 Object.defineProperty/Object.defineProperties 一塊兒使用來定義屬性,它也會受到諸如 Object.freeze/Object.seal 等方法改變。java

 

1. configurable 當且僅當 configurable 爲 true 時,該屬性纔可以被改變,也可以被刪除(delete),默認爲 false函數

var obj = {}

Object.defineProperty(obj, 'name', {
	value: 'John'
})
// 不能 delete
delete obj.name // false

Object.defineProperty(obj, 'name', {
	configurable: true,
	value: 'John'
})
// 能夠delete
delete obj.name // true

 

2. writable 當且僅當 writable 爲 true 時,該屬性才能被賦值運算符(=)改變,默認爲 falsethis

var obj = {}

Object.defineProperty(obj, 'name', {
	value: 'John'
})
obj.name = 'Backus' // 修改不起做用,仍然是 John,嚴格模式中會報錯阻止修改

Object.defineProperty(obj, 'name', {
	writable: true,
	value: 'John'
})
obj.name = 'Backus' // 被改成了 backus

 

3. enumerable 當且僅當 enumerable 爲 true 時,該屬性纔可以出如今對象的枚舉屬性(for in)中,默認爲 false對象

var obj = {}

Object.defineProperty(obj, 'name', {
	value: 'John'
})
// 不能遍歷
for (var a in obj) {
	console.log(a) // 無輸出
}

Object.defineProperty(obj, 'name', {
	enumerable: true,
	value: 'John'
})
// 能夠遍歷
for (var a in obj) {
	console.log(a) // 輸出 "name"
}

 

ES6 的 Object.keys 只返回 enumerable=true 的屬性blog

var obj = {name: 'John'}

Object.defineProperty(obj, 'name', {
	value: 'Backus',
	enumerable: true
})
Object.defineProperty(obj, 'age', {
	value: 30,
	enumerable: false
})

Object.keys(obj) // ['name']

能夠經過 propertyIsEnumerable 方法判斷屬性的 enumerable 值ip

obj.propertyIsEnumerable('name') // true
obj.propertyIsEnumerable('age')  // false

 

4. 使用 ES3(傳統的) JSON 方式定義對象,其 configurable/writable/enumerable 默認都是 true,以下get

var obj = {name: 'John', age: 30}

// configurable
delete obj.name // true
// writable
obj.age = 32 // true
// enumerable
for (var a in obj) {
	console.log(a) // age
}

也即it

var obj = {name: 'John', age: 30}

等同於io

Object.defineProperty(obj, 'name', {
	value: 'John',
	configurable: true,
	writable: true,
	enumerable: true
})
Object.defineProperty(obj, 'age', {
	value: 33,
	configurable: true,
	writable: true,
	enumerable: true	
})

  

5. 使用 ES5 的 Object.defineProperty/Object.defineProperties 方式定義對象,其 configurable/writable/enumerable 默認都是 false,以下

var obj = {}

Object.defineProperty(obj, 'name', {
	value: 'John'
})
Object.defineProperty(obj, 'age', {
	value: 33
})

// configurable
delete obj.name // false
// writable
obj.age = 32 // false
// enumerable
for (var a in obj) {
	console.log(a) // 無輸出,不能遍歷
}

也即

Object.defineProperty(obj, 'name', {
	value: 'John'
})

等同於

Object.defineProperty(obj, 'name', {
	value: 'John',
	configurable: false,
	writable: false,
	enumerable: false		
})

 

數據屬性描述符彙總以下

 

2、存取屬性描述符

存取描述符是由一對 getter-setter 函數功能來描述的屬性,格式爲

name: {
	get: function() { ... },
	set: function(newVal) { ... },
	enumerable: true,
	configurable: true
}

 

例如

var obj = {}

Object.defineProperty(obj, 'name', {
	configurable: true,
	enumerable: true,
	get: function() {
		console.log('get')
		return this.value
	},
	set: function(newVal) {
		console.log('set')
		this.value = newVal
	}
})

// 賦值會調用 set 方法
obj.name = 'John'
// 取值會調用 get 方法
obj.name

 

與上述的屬性描述符只能存在一種,即二選一,不能同時存在,不然會報錯

var obj = {}

// 錯誤方式一
Object.defineProperty(obj, 'name', {
	value: 'John',
	get: function() {
		console.log('get')
		return this.value
	}
})

// 錯誤方式二
Object.defineProperty(obj, 'name', {
	writable: true,
	get: function() {
		console.log('get')
		return this.value
	}
})

 

Firefox 報錯以下

 

存取描述符彙總以下

 

3、和屬性描述符相關的幾個函數

  1. Object.defineProperty
  2. Object.defineProperties
  3. Object.getOwnPropertyDescriptor

 

Object.defineProperty 上面已經介紹過,Object.defineProperties 批量定製對象屬性,內部其實循環方式調用 Object.defineProperty

Object.defineProperties(obj, {
	name: {
		value: 'John',
		writable: true
	},
	age: {
		value: 30,
		enmuerable: true
	}
})

 

Object.getOwnPropertyDescriptor 返回該對象某屬性的描述器,描述器自身是一個對象

var obj = {}

Object.defineProperty(obj, 'name', {
	value: 'Backus',
	writable: true,
	enumerable: true
})

var des = Object.getOwnPropertyDescriptor(obj, 'name')
console.log(des) 

輸出如圖

相關文章
相關標籤/搜索