Object.defineProperty实践

概述

Object.defineProperty() 用于在对象上定义新属性或修改现有属性,并返回修改后的对象;之所以使用 defineProperty() ,是因为它能精确的控制属性。

Object.defineProperty() 方法有三个参数,参数一是欲新增或修改属性的对象,参数二是属性名称,参数三是属性描述符;属性的描述符用于声明属性的其它特性,如:属性值、属性是否可读写、属性是否可再配置、属性是否可删除、属性的Get/Set方法等;


普通属性的定义和赋值

let Person = {}
Person.name = 'Jack'
Person['gender'] = 'female'


使用Object.defineProperty()进行属性的定义和赋值

// 1.添加属性
let obj = {};
Object.defineProperty(obj, 'name', {value:'steve'});
obj.name;  // 'steve'

// 2.修改现有属性,重返18岁
obj.age = 27;
Object.defineProperty(obj, 'age', {value:18});
obj.age; // 18


属性的特性

JS中有三种属性:

  1. 数据属性:拥有确定值的普通属性;
  2. 访问器属性:通过 gettersetter 进行读取和赋值的属性;
  3. 内部属性:由 JS 引擎内部使用的属性,外部不能直接访问,但可通过一些方法间接读取和设置,如:[[Scopes]]

每个对象都有一个内部属性[[Prototype]],代码中不能直接访问,但可通过 Object.getPrototypeOf() 间接读取。


属性描述符(descriptor)

属性描述符有两种,分别为数据描述符和存取描述符,两者不可同时使用,如下详解:

1>. 存取描述符:(getter、setter)

let Person = {}
let temp = null

Object.defineProperty(Person, 'name', {
  get: function () {     // 为属性添加 getter 方法
    return temp
  },
  set: function (val) {  // 为属性添加 setter 方法
    temp = val
  }
})
temp = 'steve'
console.log(Person.name)  // steve

2>. 数据描述符和存取描述均具有以下描述符:(value、configurable、enumerable、writable)

let Person = {}

Object.defineProperty(Person, 'name', {
  value: 'jobs',      // 属性值
  configurable:false, // 设置属性可否再配置、可否删除
  enumerable:false,   // 设置该属性的 key 是否可以被 for in 或者 Object.keys() 遍历
  writable: true,     // 是否可写(该属性值是否可改变,如果不设置,默认为 false,不可改变)
})

delete Person.name  // false

// 重新修改 Person 类的 class 属性配置,报错,Cannot redefine property!
Object.defineProperty(Person, 'name', {
   value: 2,
})

当一个属性的 configurable 被设置为 false 之后,则不能重新定义这个属性,也不能删除这个属性。

configurablefalse 时,可以把 writable 的状态由 true 改为 false,但是无法由 false 改为 true。当 configurabletrue 时,writable 的状态可以随意更改。


默认值

如果属性描述符中某些配置被省略,则默认配置如下:

let Person = {}
Object.defineProperty(Person, 'name', {})
// 等价于
Object.defineProperty(Person, 'name', {
  value: undefined,
  writable: false,
  enumerable:false,
  configurable:false,
  get:undefined,
  set:undefined
})


普通属性普通

let Person = {}
Person.name = 'steve'
// 等价于
Object.defineProperty(Person, 'name', {
  value: 'steve',
  writable: true,
  enumerable:true,
  configurable:true
})


详见MDN

其它:https://cloud.tencent.com/developer/article/1769810


举报

© 著作权归作者所有


1