开饭啦开饭啦,Object.defineProperty()详解

Object.defineProperty(obj,prop,descriptor)

  • Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
  • 直接在 Object 构造器对象上调用此方法
  • 参数1(obj):要定义属性的对象。
  • 参数2(prop):要定义或修改的属性的名称或 Symbol
  • 参数3(descriptor):要定义或修改的属性描述符

其中参数3(descriptor)存在的属性描述符有两种主要形式:数据描述符存取描述符。其中存取描述符是由getter和setter函数所描述的,一个描述符只能是其中之一,不能同时是两者

上菜上菜

  const new_obj = {}; // 创建一个空的对象
  
  // key_name1也可以是一个symbol.for('名称')
  Object.defineProperty(new_obj,'keyName_1',{
    value:99, // 给'keyName_1赋值为99'
    writable:true,
    enumerable:true,
    configurable:true
  })
  console.log(new_obj.keyName_1); // 输出99

再给”keyName_1“赋值的时候是不是多了几个不认识的属性?别急别急,开胃小菜来了

  • configurable:只有该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
    默认为 false
  • enumerable:只有该属性的 enumerable 键值为 true 时,该属性才会被枚举默认为 false
  • value:该属性对应的值,默认为 undefined
  • writable:只有该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。默认为 false

enumerable例子

  Object.defineProperty(new_obj,'keyName_2',{
    value:98,
    enumerable:true 
  })
  Object.defineProperty(new_obj, 'keyName_3', {
      value: 97,
      enumerable: false
  })
  new_obj.keyName_4 = 96; // 直接赋值方式创建,则enumerable为true
  
  new_obj.propertyIsEnumerable('keyName_1') // true
  new_obj.propertyIsEnumerable('keyName_2') // true
  new_obj.propertyIsEnumerable('keyName_3') // false
  new_obj.propertyIsEnumerable('keyName_4') // true
  for(let i in new_obj){
    console.log(i);
  }

  console.log({...new_obj});

输出结果如下
在这里插入图片描述

configurtable例子

  // configurable
  Object.defineProperty(new_obj,'keyName_5',{
    value:95,
    configurable:true
  })
  Object.defineProperty(new_obj,'keyName_6',{
    value:94,
    configurable:false
  })
  Object.defineProperty(new_obj,'keyName_7',{
    get(){return 93},
    configurable: false
  })
  // 试着删除‘keyName_5’
  delete new_obj.keyName_5; // 删除成功
  // 试着删除‘keyName_6’
  delete new_obj.keyName_6; // 报错keyName_6
  // 试着修改‘keyName_7’
  Object.defineProperty(new_obj,'keyName_7',{
    get(){ return 92 }
  })

输出结果如下
在这里插入图片描述

writable的例子

  // writable
  Object.defineProperty(new_obj,'keyName_8',{
    value:92,
    writable:false
  })
  Object.defineProperty(new_obj,'keyName_9',{
    value:789,
    writable:true
  })
  // 修改keyName_9
  new_obj.keyName_9 = 91;
  // 修改keyName_8
  new_obj.keyName_8 = 789;

输出结果如下
在这里插入图片描述

添加多个属性和默认值

  • 赋予默认值是非常重要的,通常,使用点运算符和 Object.defineProperty() 为对象的属性赋值时,数据描述符中的属性默认值是不同的,如下例所示。
  // 默认值
  new_obj.keyName_10 = 90; // 点运算符
  // 等同于
  Object.defineProperty(new_obj,'KeyName_10',{
    value:90,
    writable:true,
    configurable:true,
    enumerable:true
  })

  // Object.defindProperty()添加
  Object.defineProperty(new_boj,'KeyName_11',{ value:89 });
  // 等同于
  Object.defineProperty(new_boj,'keyName_11',{
    value:89,
    writable: false,
    configurable: false,
    enumerable: false
  })

设置set和get方法

  // 自定义set 和 get
  Object.defineProperty(new_boj,'keyName_12',{
    get(){
      console.log('keyName_12被获取了')
      // 我也可以在这里不返回值,是先变量的私有
      return keyName_12
    },
    set(val){
      // 我也可以在这里不让他设置,实现变量的私有
      console.log('keyName_12被重新赋值了')
      keyName_12 = val
    }
  })

请注意:get和set这种方法有缺陷,一个值只有先设置才能获取!!!

 // 第二个例子
 const obj = {
	 let name = 'aaa';
	 let age = 18;
 }
  Object.defineProperties(obj,{
    "name":{
      get(){
        console.log('obj的name被获取了')
        return name
      },
      set(val){
        console.log('obj的name被设置了')
        name = val
      }
    },
    "age":{
      get(){
        console.log('obj的age被获取了')
        return age
      },
      set(val){
        console.log('obj的age被设置了')
        age = val
      }
    }
  })

继承属性

function myClass(){}
  let value;
  Object.defineProperty(myClass.prototype,'A',{
    get(){
      return value
    },
    set(val){
      valut = val
    }
  })
  let m1 = new myClass();
  let m2 = new myClass();
  m1.A = 200;
  console.log(m2.A); // 200

可以看到给m1设置的变量,通过m2也能访问到,这明显是不合理的

  function myClass(){}
  let value;
  myClass.prototype.A = 1;
  Object.defineProperty(myClass.prototype,'B',{
    writable:false,
    value:1
  })

  let m1 = new myClass();
  m1.A = 200;
  console.log(m1.A) // 200
  console.log(myClass.prototype.A); // 1
  m1.B = 100;
  console.log(m1.B) // 1
  console.log(myClass.prototype.B); // 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值