Object.defineProperty()详解

438 阅读3分钟

语法

Object.defineProperty(obj, prop, descriptor)

Object.defineProperty()方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性并返回这个对象。 这个方法需要三个参数(obj,prop,descriptor)

参数

  1. obj 对象 -> 给哪个对象加
  2. prop 属性名 -> 要加的属性的名字 [类型:string]
  3. descriptor 属性描述 -> 加的这个属性有什么样的特性 [类型:Object]

descriptor中的数据描述符

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值是可写可不写的。存取描述符是有getter函数和setter函数所描述的属性。数据描述符和存取描述符不能同时使用。

  1. configurable:仅当该属性的configurable为true时,该属性才能够被改变,也能被删除。默认为false
  2. enumerable:仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为false
  3. value:该属性对应的值。可以是任何有效的JavaScript值(数值、对象、函数等)。默认是undefined
  4. writable:仅当该属性的writable为true时,该属性才能被赋值运算符改变,默认是false
  5. get:一个给属性提供getter方法,如果没有getter则为undefined。该方法返回值被用作属性值,默认undefined
  6. set:一个给属性提供setter方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认是undefined

1、configurable

configurable特性表示对象的属性是否可以被删除,以及除value和writable特性以外的其它特性是否可以被修改。当configurable为false时,其他属性不管有没有写出来(有默认值),都无法被重新定义或修改。

   const user = {
      name:'a'
   }
   Object.defineProperty(user,'name',{
     configurable:false
   })
   console.log(user.name)             //{name:'a'}
   delete user.name;
   console.log(user.name)             //{name:'a'}
   
   
   Object.defineProperty(user,'name',{
      configurable:true
   })
   console.log(user.name)            //{name:'a'}
   delete user.name
   console.log(user.name)            //{ }
   
   
   
   Object.defineProperty(user,'name',{
      get() {
         return b
      },
      configurable:false
   })
   console.log(user.name)          //{name:'b'}
   delete user.name                
   console.log(user.name)          //{name:'b'}
  
    
   
   Object.defineProperty(user,'name',{
     get() {
       return b
     }
   })
   console.log(user.name)         //throws a TypeError

通过这个属性设置好configurable属性,就不能把user里的name删除了。如果configurable属性为true,则不会抛出任何错误,并且该属性最后会被删除。

2、writable

   Object.defineProperty(user,'name',{
     value:'b',
     writable:false
   })
   console.log(user.name)                //b
   user.name = 'c'
   console.log(user.name)                //b

通过这个属性设置只读,就不能修改user里的name值了

3、value

   Object.defineProperty(user,'name',{
     value:'hhh'
   })
   console.log(user.name)            //hhh
   
   
   //添加多个属性值和默认值
   const obj = {}
   obj.age = 10
   //等同于
   Object.defineProperty(obj,'age',{
      value:10,
      writable:true,
      configurable:true,
      enumerable:true
   })
   
   Object.defineProperty(obj,'age',{value:10});
   //等同于
   Object.defineProperty(obj,'age',{
     value:10,
     writable:false,
     cofigurable:false,
     enumerable:false
   })

通过这个属性给user里的name赋值

4、enumerable

enumerable定义的属性可以在Object.keys()中被枚举。

   const user = {
      name:'a',
      age:15
   }
   Object.defineProperty(user,'sex',{
      vale:'男',
      enumerable:true
   })
   user.propertyInsEnumerable('sex')     // true
   Object.keys(user)   //['name','age','sex']
   console.log(user)   //{name:'a',age:15,sex:'男'}
   user.time = '2022'     //如果使用直接赋值的方法创建对象的属性,则enumerable为true
   
   
   
   Object.defineProperty(user,'sex',{
      vale:'男',
      enumerable:false
   })
   user.propertyInsEnumerable('sex')     //false
   Object.keys(user)   //['name','age']
   console.log(user)   //{name:'a',age:15}
    

通过这个属性决定user里的sex是否能枚举

5、get

get是获取值的时候触发,类型为function,获取值的时候会被调用,不设置是undefined

   const user = {
      name:'a'
   }
   const count = 10
   Object.defineProperty(user,'age',{
      get:function(){
         return count;
      }
   })
   console.log(user.age);         //10

6、set

set是设置值的时候触发,类型是function,设置值的时候会被调用,不设置是undefined

   const user = {
      name:'a'
   }
   const count= 10;
   Object.defineProperty(user,'age',{
      get:function(){
        return count;
        console.log('获取值')
      },
      set:function(val){
        console.log('设置值')
        return val+1
      }
   })
   
   console.log(user.age)    //10   //获取值
   user.age = 100;
   console.log(user.age)    //设置值   //获取值   //101