什么是属性
在 Javascript 中, 属性 由一个字符串类型的“名字”(name)和一个“属性描述符”(property descriptor)对象构成。我们平常只关注了属性值,而没有关注更多的属性描述符;
从以上的属性描述可以看出,我们可以修改属性的 属性描述符 来设置属性对外特性,这种特性会约束属性的操作或者对外提供的功能;
Object 作为js中对象的基础对象,提供了以下三个方法:
- Object.freeze();
- Object.seal();
- Object.preventExtensions();
就三个提供的功能来讲,我们可以猜测是如何做到的?
参考:defineProperty 属性是有一组属性描述符组成的,具体含义查看MDN:
{
configurable: false,
enumerable: false,
value: undefined,
writable: false,
get() {
return ...
},
set(x){
... = x;
}
}
以上三个方法,就是的参数都是对象,是对参数对象的进行作用,并且是对参数对象中所有属性的描述符进行修改,来达到方法的作用;
如何查看一个对象的属性描述符
Object.getOwnPropertyDescriptors(obj);
此方法,只有个参数,将需要查看的对象传入,便可以返回对象的每一个 属性的属性描述符;
比如:
Object.getOwnPropertyDescriptors({ a: 1,b: 2,c: 3 });
输出
{
"a": {
"value": 1,
"writable": true,
"enumerable": true,
"configurable": true
},
"b": {
"value": 2,
"writable": true,
"enumerable": true,
"configurable": true
},
"c": {
"value": 3,
"writable": true,
"enumerable": true,
"configurable": true
}
}
Object.freeze()
const obj = {a: 1};
Object.freeze(obj);
// 冻结前
{
"a": {
"value": 1,
"writable": true,
"enumerable": true,
"configurable": true
}
}
// 冻结后
{
"a": {
"value": 1,
"writable": false,
"enumerable": true,
"configurable": false
}
}
结论:
从属性描述符来看,更改了两个属性,
writable=false, configurable=false,表明属性只读,不可以修改,同时属性描述符不可以再修改;
者就是我们平日看到的,被冻结后的现象;不能重新赋值了;
delete obj.a 也会是被,因为 configurable被设置为false,不允许将属性从对象中移除;
Object.preventExtensions()
阻止对象中属性扩展,既然是扩展,那么就是拒绝增加属性,但可以删除属性;
// 组织前
{
"a": {
"value": 1,
"writable": true,
"enumerable": true,
"configurable": true
}
}
// 阻止后
{
"a": {
"value": 1,
"writable": true,
"enumerable": true,
"configurable": true
}
}
已有属性描述符,并没有变化;
我们可以使用方法Object.isExtensible(obj)来查看当前对象是否 可以扩展,Object.preventExtensions 的作用标记是记录在对象本身上的;因此我们在给对象增加属性时,内部会参考这个标志来决定是扩展;
obj.b = 2;
console.log(obj); // 输出:{a: 1} 表明无法在增加属性
delete obj.a //返回 ture;
console.log(obj); // 输出:{} 表明删除属性成功
Object.seal()
密封对象的属性;
// 密封前
{
"a": {
"value": 1,
"writable": true,
"enumerable": true,
"configurable": true
}
}
// 密封后
{
"a": {
"value": 1,
"writable": true,
"enumerable": true,
"configurable": false
}
}
密封后
- configurable属性,被设置为false;
所以密封后,我们是可以修改属性值 obj.a = 2;
delete obj.a 将是被,不可以删除;
- Object.isExtensible(obj) 返回false,表示不可扩展,因此 obj.b = 2; 增加属性失败;
结论:
密封是来源于面向对象编程,对象被密封后,属性被保护起来了,禁止增加和删除属性,但属性值本身是可以修改的;
结论
- preventExtensions 可删除和修改源属性,不可添加新属性
- seal 可修改但是不可删除源属性,不可添加新属性
- freeze 不可修改和源属性,不可添加新属性,三者中最严格;