JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。
{
value: "zhang", //该属性的属性值,默认为undefined。
writable: false, //表示属性值(value)是否可改变(即是否可写),默认为true。
enumerable: true, // 表示该属性是否可遍历,默认为true。如果设为false,会使得某些操作(比如for...in循环、Object.keys())跳过该属性。
configurable: false, //表示可配置性,默认为true。如果设为false,将阻止某些操作改写该属性,比如无法删除该属性,也不得改变该属性的属性描述对象(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。
get: undefined, //表示该属性的取值函数(getter),默认为undefined。
set: undefined //表示该属性的存值函数(setter),默认为undefined。
}
对象上的方法
-
Object.getOwnPropertyDescriptor()
获取属性描述对象。它的第一个参数是一个对象,第二个参数是一个字符串,对应该对象的某个属性名。
let obj = { name: "zhang" }
Object.getOwnPropertyDescriptor(obj,"name")
{
value: "zhang",
writable: true,
enumerable: true,
configurable: true
}
//只能用于对象自身的属性,不能用于继承的属性
-
Object.getOwnPropertyNames()
返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。
let obj = { name: "zhang" }
Object.getOwnPropertyNames(obj) //["name"]
-
Object.defineProperty(),Object.defineProperties()
Object.defineProperty方法允许通过属性描述对象,定义或修改一个属性,然后返回修改后的对象,该方法接受三个参数(属性所在的对象,属性名(它应该是一个字符串,属性描述对象)
var obj = Object.defineProperty({}, 'p', {
value: 123,
writable: false,
enumerable: true,
configurable: false
});
obj.p // 123
如果一次性定义或修改多个属性,可以使用Object.defineProperties方法。
var obj = Object.defineProperties({}, {
p1: { value: 123, enumerable: true },
p2: { value: 'abc', enumerable: true },
p3: { get: function () { return this.p1 + this.p2 },
enumerable:true,
configurable:true
}
});
obj.p1 // 123
obj.p2 // "abc"
obj.p3 // "123abc"
//定义了get或set,不能将writable属性设为true,或者定义value属性,
-
Object.prototype.propertyIsEnumerable()
判断某个属性是否可遍历,返回一个布尔值。
let obj = { name: "zhang" }
obj.propertyIsEnumerable('name') // true
obj.propertyIsEnumerable('toString') // false
//继承原型对象的属性不可遍历
元属性
属性描述对象的各个属性称为“元属性”,因为它们可以看作是控制属性的属性。Vue 双向数据绑定基于该操作。
- value
let obj = { name: "zhang" }
Object.getOwnPropertyDescriptor(obj, 'name').value
Object.defineProperty(obj, 'name', { value: "li" })
obj.name // li
- writable //决定了目标属性的值(value)是否可以被改变。
var obj = {};
Object.defineProperty(obj, 'name', {
value: "zhang",
writable: false
});
obj.name // zhang
obj.name = "li"
obj.name // zhang
- enumerable // 表示目标属性是否可遍历。
var obj = {};
Object.defineProperty(obj, 'name', {
value: "zhang",
enumerable: false
});
obj.name // "zhang"
for (var key in obj) {
console.log(key);
}
// undefined
Object.keys(obj) // []
JSON.stringify(obj) // "{}"
- configurable // 是否可以修改属性描述对象,configurable为false时,value、writable、enumerable和configurable都不能被修改。
var obj = Object.defineProperty({}, 'name', {
value: "zhang",
writable: false,
enumerable: false,
configurable: false
});
Object.defineProperty(obj, 'name', {value: "T"})
/// TypeError: Cannot redefine property: name
set && get
属性还可以用存取器(accessor)定义。其中,存值函数称为setter,使用属性描述对象的set属性;取值函数称为getter,使用属性描述对象的get属性。
let obj = Object.defineProperty({}, 'name', {
get: function () {
return 'jack';
},
set: function (value) {
console.log('item: ' + value);
}
});
obj.name // "jacky"
obj.name = 123 // "item: 123"
.......................................................................
控制对象状态
有时需要冻结对象的读写状态,防止对象被改变。JavaScript 提供了三种冻结方法,最弱的一种是Object.preventExtensions,其次是Object.seal,最强的是Object.freeze。
- Object.preventExtensions()
Object.preventExtensions方法可以使得一个对象无法再添加新的属性
var obj = new Object();
Object.preventExtensions(obj);
Object.defineProperty(obj, 'name', {
value: 'zhang'
});
// TypeError: Cannot define property:name, object is not extensible.
obj.name = 1;
obj.name // undefined
- Object.isExtensible()
用于检查一个对象是否使用了Object.preventExtensions方法。也就是说,检查是否可以为一个对象添加属性。
var obj = new Object();
Object.isExtensible(obj) // true
Object.preventExtensions(obj);
Object.isExtensible(obj) // false
- Object.seal()
使得一个对象既无法添加新属性,也无法删除旧属性。
var obj = { name: 'zhang' };
Object.seal(obj);
delete obj.name;
obj.name // "zhang"
obj.text = 'world';
obj.text // undefined
//Object.seal实质是把属性描述对象的configurable属性设为false
- Object.isSealed()
检查一个对象是否使用了Object.seal方法
var obj = { name: 'AndyZhang' };
Object.seal(obj);
Object.isSealed(obj) // true
- Object.freeze()
使得一个对象无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量。
var obj = { name: 'AndyZhang' };
Object.freeze(obj);
obj.name = 'li';
obj.name // "zhang"
obj.text = 'hello';
obj.text // undefined
//obj对象进行Object.freeze()以后,修改属性、新增属性、删除属性都无效了。
- Object.isFrozen()
检查一个对象是否使用了Object.freeze方法
var obj = { name: 'AndyZhang' };
Object.freeze(obj);
Object.isFrozen(obj) // true
网友评论