重学js之对象的属性的描述符

123 阅读2分钟

我们先看一个例子

var obj = {
  a:2
}
a 就是对象的属性名(也就是key)  2就是属性a的值(也就是value)

从 ES5 开始,对象的属性都具备了属性的描述符,它能设置属性的特性,可以使用 Object.defineProperty(…) 来添加或者配置一个属性并对它的特性进行配置。属性有: writable、 enumerable 和 configurable 这三个或之一都为属性描述符。

 var obj ={};
 Object.defineProperty(obj,"a",{
   value:2,
   writable:true,
   enumerable:true,
   configurable:true
})
// 给对象添加一个属性a,它的值为2

Object.getOwnPropertyDescriptor() 检测对象属性描述符

var myObject = {
  a:2
}
Object.getOwnPropertyDescriptor(myObject,'a')

{
  value:2,
  writable:true,
  enumerable:true,
  configurable:true
}

writable

决定是否可以修改属性的值

var myObject = {}
Object.defineProperty(myObject,"a",{
  value:2,
  writable:false // 不可写
})
myObject.a = 3;

// 如果在严格模式下设置了writable:false 为不可写 当修改一个不可写的属性时就会报错 // TypeError

//设置writable:false  相当于定义了一个空操作setter(setter调用时抛出一个TypeError)

Configurable

可配置属性,如果把configurable属性改为false后 再去修改一个不可配置的属性描述符都会报错(即使修改writable:true,或者修改value值为其他值都会报TypeError错),configurable属性改为false是单向操作的,无法撤销

 var obj = {}
        Object.defineProperty(obj,'a',{
            value:3,
            configurable:false
        });
        Object.defineProperty(obj,'a',{
            value:4,
        });
        console.log(obj.a) // TypeError

Object.defineProperty(obj,'a',{
            configurable:true
        });
        console.log(obj.a) // TypeError

Object.defineProperty(obj,'a',{
            writable:true
        });
        console.log(obj.a) // TypeError

 
 // 

    var obj = {
            name: 11
        }
        Object.defineProperty(obj, 'name', {
            value: 3,
            configurable: false
        });
        Object.defineProperty(obj, 'name', {
            value: 9,
        });

        console.log(obj.name) // 9

enumerable

设置属性值是否出现在对象的属性枚举中,设置enumerable:false则该属性在for-in 循环中不会被返回,但是可以被访问

  var obj = {
            name: '杨紫'
        }
        Object.defineProperty(obj, 'age', {
            value: 18,
            enumerable: false
        });

        for (let key in obj) {
            console.log('key', key) // 只有name属性
        }

        console.log(obj.hasOwnProperty('age')); // true
        console.log('age' in obj) // true

对象常量

不可修改或重新定义或删除

  var obj = {};
        Object.defineProperty(obj, 'name', {
            value: '杨紫',
            writable: false,
            configurable: false
        });
        obj.name = '杨旎奥';
        delete obj.name;
        console.log(obj.name) // 杨紫

禁止一个对象扩展 Object.preventExtensions()

禁止一个对象添加新属性并且保留已有属性

var obj = {
  name:'杨紫'
};
Object.preventExtensions(obj);
obj.age = 18;
console.log(obj.age)//非严格模式undefined  严格模式 TypeError

禁止扩展与“冻结”对象 与“密封”对象