对象中的属性类型
描述:ES5在定义只有内部采用的特性attribute
时,描述了属性property
的各种特征。ECMA-262
定义这些特征是为了实现JavaScript
引擎用的,因此在 JavaScrip
中不能直接访问他们。
ECMAScript中有两种属性:数据属性和访问器属性
1. 数据属性
- [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。对于直接在对象上定义的属性,默认值为
true
。 - [[Enumerable]]:表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性,默认值为
true
。 - [[Writable]]:表示能否修改属性的值。
- [[Value]]:包含这个属性的数据值。读取属性时,从这个位置读;写入属性时,把新值保存在这个位置。默认是
undefined
。
var obj1 = new Object()
obj.name = 'jinxing'
var obj2 = {
name: 'jinxing'
}
注:创建一个Object
实例或者使用对象字面量的方式创建的对象,它们的 [[Configurable]]、[[Enumerable]]、[[Writable]] 特性都被设置true
,[[Value]] 特性会被设置为jinxing
,而对这个值然和的修改,都会反映在 [[Value]] 上。一个对象中的每个属性都有这四个数据属性或者下面要说的四个访问器属性。
要修改属性默认的特性,就必须使用ES5的 Object.definedProperty() 方法。
描述:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法:Object.defineProperty(obj, prop, descriptor)
参数:
- obj:要定义属性的对象。
- prop:要定义或修改的属性的名称或 Symbol。
- descriptor:要定义或修改的属性描述符。
返回值:被传递给函数的对象。
// 例
var person = {}
// 对person对象上的name属性的特性进行修改
Object.defineProperty(person, 'name', {
writable: false, // 不可写
value: 'jinxing' // 值为jinxing
})
console.log(person.name) // jinxing`
person.name = 'ergou' // 无效
console.log(person.name) // jinxing
注:在非严格模式下,赋值操作将会被忽略,在严格模式下,赋值操作将会抛出错误。
configurable不可配置属性也有类似规则
// 例
var person = {}
Object.defineProperty(person, 'name', {
configurable: false, // 不能从对象中删除属性
value: 'jinxing' // 值:jinxing
})
console.log(person.name) // jinxing
delete person.name // 无效,严格模式下会报错
console.log(person.name) // jinxing
注:这个属性是不可逆的,一旦设置了configurable为true,再次调用defineProperty修改会报错。并且在调用Object.defineProperty()方法创建一个新的属性时,如果不指定,configurable,enumerbale,writable特性的默认值都是false。
2. 访问器属性
- [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。对于直接在对象上定义的属性,默认值为true。
- [[Enumerable]]:表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性,默认值为true。
- [[Get]]:在读取属性时调用的函数。默认值为undefined。
- [[Set]]:在写入属性时调用的函数。默认值为undefined。
var person = {
name: 'jinxing',
age: 20
}
Object.defineProperty(person, 'age', {
get: function() {
return this.age + 1
},
set: function(newAge) {
this.age = newAge
}
})
person.age = 25
console.log(person.age) // 26
注:不一定非要同时指定 getter 和 setter 。只指定 getter 意味着属性是不可写的,尝试写入会被忽略。在严格模式下,尝试写入只指定了 getter 的函数的属性会抛出错误。类似的,只指定 setter 函数的属性不能读,非严格模式下会返回 undefined ,严格模式下会报错。
如果想一次定义多个属性,ES5又定义了一个 Object.defineProperyies() 方法
描述:Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
语法:Object.defineProperties(obj, props)
参数:
- obj:在其上定义或修改属性的对象。
- props:要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符。描述符具有以下键:
- configurable:
true
当且仅当该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。默认为 false - enumerable:
true
当且仅当在枚举相应对象上的属性时该属性显现。默认为 false - value:与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)。默认为 undefined.
- writable:
true
当且仅当与该属性相关联的值可以用赋值运算符改变时。默认为 false - get:作为该属性的 getter 函数,如果没有 getter 则为
undefined
。函数返回值将被用作属性的值。默认为 undefined - set:作为属性的 setter 函数,如果没有 setter 则为
undefined
。函数将仅接受参数赋值给该属性的新值。默认为 undefined
- configurable:
返回值:传递给函数的对象。
var person = {}
Object.defineProperties(person, {
_name: {
value: 'jinxing'
},
age: {
value: 20
},
name: {
get: function() {
return this._name
},
set: function(newName) {
this._name = newName
this.age++
}
}
})
注:以上代码person
对象中定义了两个属性(_name
和age
)和一个访问器属性(name
)
读取属性的特征:Object.getOwnPropertyDescriptor()方法
描述:Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
语法:Object.getOwnPropertyDescriptor(obj, prop)
参数:
- obj:需要查找的目标对象
- prop:目标对象内属性名称
返回值:如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回undefined
。
// 对象例子参考上一段代码 这里直接展示打印结果
var descriptor = Object.getOwnPropertyDescriptor(person, '_name')
console.log(descriptor.value) // jinxing
console.log(descriptor.configurable) // false(默认)
console.log(typeof descriptor.get) // undefined
// --------
var descriptor = Object.getOwnPropertyDescriptor(person, 'name')
console.log(descriptor.value) // undefined
console.log(descriptor.enumerable) // false(默认)
console.log(typeof descriptor.get) // function