当前位置:   article > 正文

Object.defineProperty() 详解

object.defineproperty

一、对象的定义与赋值

我们经常使用的定义与赋值方法 obj.xxx = value 或 obj['xxx'] = value,并且可以定义任意类型的值,如下所示:

  1. let obj = {};
  2. obj.name = 'bjl';
  3. obj['age'] = 18;
  4. obj.sayHi = function() {console.log('Hi')};
  5. console.log(obj) // {name: 'bjl', age: 18, sayHi: fn}

二、Object.defineProperty() 语法

Object.defineProperty() 的作用就是直接在一个对象上定义新属性,或者修改一个已经存在的属性。语法格式为:

Object.defineProperty(object, propName, descriptor);
  1. object:需要定义属性的当前对象
  2. propName:当前需要定义的属性名
  3. descriptor:属性描述符

三、属性描述符

都有哪些属性描述符呢?如下:

  • value:设置属性的值
  • writable:值是否可以重写
  • set:目标属性设置值的方法
  • get:目标属性获取值的方法
  • enumerable:目标属性是否可以被枚举(是否可以遍历)
  • configurable:目标属性是否可以被删除或是否可以再次修改特性

通过 Object.defineProperty() 为对象定义属性有两种形式,但不能混合使用,分别是数据描述符、存取描述符。

1. 数据描述符(value、writable)

当使用了 value 和 writable 属性,不允许使用 getter 或 setter 这两个方法。

  • value:设置属性值
  1. let obj = {};
  2. Object.defineProperty(obj, 'name', {
  3. value: 'bjl'
  4. })
  5. console.log(obj.name) // bjl
  • writable:描述对象是否可写,默认值为false,表示只读属性
  1. let obj = {};
  2. Object.defineProperty(obj, 'name', {
  3. value: 'bjl'
  4. })
  5. obj.name = 'bao';
  6. console.log(obj.name) // bjl
  1. let obj = {};
  2. Object.defineProperty(obj, 'name', {
  3. value: 'bjl',
  4. writable: true // 表示可以进行修改
  5. })
  6. obj.name = 'bao';
  7. console.log(obj.name) // bao
  1. let obj = {
  2. name: 'bjl'
  3. };
  4. Object.defineProperty(obj, 'name', {
  5. writable: false //手动设置name属性不可被修改
  6. })
  7. obj.name = 'bao';
  8. console.log(obj.name) // bjl

当声明一个对象时,它里面的属性的内部属性的默认值都为 true,也就是说 writable 这时的默认值为 true,这就是为什么上面的 name 如果不想被修改就需要手动去设置 writable 属性的原因。我们可以使用 Object.getOwnPropertyDescriptors() 去检测属性的内部属性的具体描述,如下:

  1. let obj = {
  2. name: 'bjl'
  3. }
  4. console.log(Object.getOwnPropertyDescriptors(obj))
  5. Object.defineProperty(obj, 'age', {
  6. value: 18
  7. })
  8. console.log(Object.getOwnPropertyDescriptors(obj))

打印如下:

 2. 存储描述符(get、set)

当使用 get 或 set 方法,不允许使用 value 和 writable 这两个属性。

  • get:一个给属性提供 getter 的方法,默认值为 undefined
  • set:一个给属性提供 setter 的方法。默认值为 undefined,该方法接受唯一的参数,并将该参数的新值分配给该属性
  1. let obj = {};
  2. let temp = 'bjl';
  3. Object.defineProperty(obj, 'name', {
  4. get: function() {
  5. return temp
  6. },
  7. set: function(val) {
  8. temp = val
  9. }
  10. })
  11. console.log(obj.name) // bjl
  12. // 当修改属性时,就会触发方法里的set方法
  13. obj.name = 'bao';
  14. console.log(obj.name) // bao

3. enumerable:表示目标属性是否可以被枚举

有时我们会对对象进行遍历,只有被枚举的属性可以被遍历到,如下所示:

  • for...in...
  1. let obj = {
  2. name: 'bjl',
  3. age: 18
  4. }
  5. Object.defineProperty(obj, 'sex', {
  6. value: '女'
  7. })
  8. for(let key in obj) {
  9. console.log(key) // name age
  10. }
  • Object.keys()
  1. let obj = {
  2. name: 'bjl',
  3. age: 18
  4. }
  5. Object.defineProperty(obj, 'sex', {
  6. value: '女'
  7. })
  8. console.log(Object.keys(obj)) // ['name', 'age']
  9. Object.keys(obj).map(key => {
  10. console.log(key) // name age
  11. })

我们可以看出,使用 Object.defineProperty() 添加的属性不能被枚举到,也就是不能被遍历到。Object.keys() 返回的是可以被枚举到的数组,所以打印结果如上所述。

添加 enumerable 描述属性可以改变,如下所示:

  1. let obj = {
  2. name: 'bjl',
  3. age: 18
  4. }
  5. Object.defineProperty(obj, 'sex', {
  6. value: '女',
  7. enumerable: true
  8. })
  9. console.log(Object.keys(obj)) // ['name', 'age', 'sex']
  10. Object.keys(obj).map(key => {
  11. console.log(key) // name age sex
  12. })

4. configurable:目标属性是否可以被删除或是否可以再次修改特性

  • 对象原属性默认为 true,可以被删除
  1. let obj = {
  2. name: 'bjl',
  3. age: 18
  4. }
  5. delete obj.name;
  6. console.log(obj) // {age: 18}
  • Object.defineProperty() 内部属性为 false,不可被删除
  1. let obj = {
  2. name: 'bjl',
  3. age: 18
  4. }
  5. Object.defineProperty(obj, 'sex', {
  6. value: '女'
  7. })
  8. delete obj.sex;
  9. console.log(obj) // {name: 'bjl', age: 18, sex: '女'}
  • 使用 configurable 属性设置可以删除属性
  1. let obj = {
  2. name: 'bjl',
  3. age: 18
  4. }
  5. Object.defineProperty(obj, 'sex', {
  6. value: '女',
  7. configurable: true
  8. })
  9. Object.defineProperty(obj, 'name', {
  10. configurable: true
  11. })
  12. delete obj.sex;
  13. delete obj.name;
  14. console.log(obj) // {age: 18}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/123869
推荐阅读
相关标签
  

闽ICP备14008679号