[Js进阶]Object.freeze、Object.seal、defineProperty关系简介

Object.freeze、Object.seal、defineProperty关系简介

defineProperty简介

defineProperty即给对象定义属性

语法:Object.defineProperty(obj,property,descriptor)

参数一:obj
绑定属性的目标对象
参数二:property
绑定的属性名
参数三:descriptor
属性描述(配置),且此参数本身为一个对象

  • 属性值1:value
    设置属性默认值
  • 属性值2:writable
    设置属性是否能够修改
  • 属性值3:enumerable
    设置属性是否可以枚举,即是否允许遍历
  • 属性值4:configurable
    设置属性是否可以删除或编辑
  • 属性值5:get
    获取属性的值
  • 属性值6:set
    设置属性的值

功能一:通过value设置属性值

由于Object.defineProperty可以给对象定义属性,我们通过value,可以动态地将obj对象的属性动态地添加给target中。

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key]
  })
}
console.log(target);

功能二:通过writable设置是否可写/修改

1.当writable的值为false时

尝试将count的值从0改为10

writable默认值为false,即不加writable方法,target的值也不可写/修改

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key],
    writable: false
  })
}
target.count = 10;//将count中的值0修改成10
console.log(target.count);
// 当writable为false时,无法改变count的值

2.当writable的值为true时
尝试将count的值从0改为10

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key],
    writable: true
  })
}
target.count = 10;//将count中的值0修改成10
console.log(target.count);
// 当writable为true时,可以改变count的值

功能三:通过enumerable设置属性值是否允许遍历

在上面的代码基础上,我们添加enumerable属性并尝试遍历target中的属性值

enumerable默认值为false

1.当enumerable的值为false时

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key],
      writable:true,
      enumerable: false
  })
}
for (key in target){
  console.log(key);//遍历target中的属性值并打印,此时结果为空
}

2.当enumerable的值为true时

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key],
      writable:true,
      enumerable: ture
  })
}
for (key in target){
  console.log(key);//成功遍历对象并打印出结果
}

功能四:通过configurable设置属性是否可删

在上面的代码基础上,我们添加configurable属性并尝试用delete方法删除target中的属性

1.当configurable的值为false时

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key],
    writable:true,
    enumerable: falseconfigurable: false
  })
}
delete target.count;//删除count属性
console.log(target);  // 显示count属性还在

【注意】configurable默认值为false,即不加configurable方法,target的属性也不可删除

2.当configurable的值为true时

for (let key in obj){
  Object.defineProperty(target,key,{
    value: obj[key],
    writable:true,
    enumerable: falseconfigurable: true
  })
}
delete target.count;//删除count属性
console.log(target); // 成功删除count属性并打印target

功能五:通过get方法获取属性的值

【注意!】当设置get方法时,不能有value和writable方法,否则会报错
get方法的值是一个函数,此函数不需要参数

for (let key in obj){
  Object.defineProperty(target,key,{
    //value: obj[key],
    //writable:true,
    enumerable: false,
    configurable: true,
    get: function(){
      return obj[key]
    }
  })
}
console.log(target.count); // 成功获取到了指定属性(count)的值

【注意】get方法只有在获取指定属性值的时候,才会触发,即调用get下的匿名函数

功能六:通过set方法设置属性的值

set方法的值也是一个函数,定义时会自动注入一个参数,此参数会设置属性的值

for (let key in obj){
  Object.defineProperty(target,key,{
    //value: obj[key],
      //writable:true,
      enumerable: false,
      configurable: true,
      get: function(){
        return obj[key]
    }set: function(val){
      console.log(val);//打印设置好的值
    }
  })
}
target.count = 10;//修改count属性的值为10
// 成功修改了指定属性(count)的值

【注意】set方法只有在设置/修改指定属性值的时候,才会触发,即调用set下的匿名函数

target与obj的比较:

  • target与obj都是对象,且通过defineProperty方法处理后,二者的值动态相等。
    即增加、修改或删除其中任意对象的属性,另一对象也会相应地进行变化。 类似与defineProperty方法将二者以某种方式连在了一起。
  • target === obj 的结果为false,即二者并非同一个对象

Object.freeze()

Object.freeze()可以提高性能。

如果有一个对象,里面的内容特别特别多,而且都是一些静态数据,你确保不会修改它们,那你其实可以用Object.freeze()冻结起来,这样可以让性能大幅度提升,提升的效果随着数据量的递增而递增。一般什么时候用呢?对于纯展示的大数据,都可以使用Object.freeze提升性能。

模拟Object.freeze()原理主要用到两个关键方法Object.definedProperty()Object.seal()

Object.definedProperty()方法可以定义对象的属性的特性。如可不可以删除、可不可以修改等等

Object.defineProperty(person, 'name', {
    configurable: false, // 表示能否通过delete删除属性,能否修改属性的特性...
    enumerable: false,   // 表示是否可以枚举。直接在对象上定义的属性,基本默认true
    writable: false,     // 表示能否修改属性的值。直接在对象上定义的属性,基本默认true
    value: 'xm'          // 表示属性的值。访问属性时从这里读取,修改属性时,也保存在这里。
})

通过上述配置,就能实现不能修改已有属性的值、不能修改已有属性的可枚举性、可配置性、可写性等等功能了

Object.seal()方法可以让对象不能被扩展、删除属性等等。用法:Object.seal(person)

通过Object.seal()方法可以实现不能删除,不能新增对象属性等等功能。通过这两个方法就可以实现一个简单的freeze方法了

function myFreeze(obj) {
  if (obj instanceof Object) {
    Object.seal(obj);
    for (let p in obj) {
      if (obj.hasOwnProperty(p)) {
        Object.defineProperty(obj, p, {
          writable: false
        });
        myFreeze(obj[p]);
      }
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值