详解 Object.defineProperty() & Object.defineProperties()

文章归档于:https://www.yuque.com/u27599042/front-end


Object.defineProperty()

  • 该方法用于在一个对象上定义一个新属性,或者修改一个对象上已有的属性,并返回修改后的原对象
Object.defineProperty(obj, prop, descriptor)
  • 该方法需要传递三个参数:
    • obj:需要定义新属性或修改属性的对象
    • prop:一个字符串或 Symbol,指明要定义新属性或修改属性的 key
    • descriptor:对定义的新属性或修改的属性的描述符,描述指定的属性是否可以修改、是否可以删除等
  • 该方法返回传入的对象,该对象指定的属性已被新增或修改

描述指定属性的值 value

<script>
  let person = {
    name: 'zs',
    sex: 'male'
  }
  // 向 person 对象中新添加一个 age 属性
  // 同时指定新添加的属性值为 18
  Object.defineProperty(person, 'age', {
    value: 18
  })
  console.log(person)
script>

描述指定属性是否可枚举 enumerable

  • 使用 Object.defineProperty() 添加的属性默认是不可枚举,即使用 Object.defineProperty() 添加的属性默认是不能进行遍历的。
  <script>
    let person = {
      name: 'zs',
      sex: 'male'
    }
    // 向person对象中新添加一个age属性
    Object.defineProperty(person, 'age', {
      value: 18
    })
    console.log(person)
    console.log(Object.keys(person))
    for (let key in person) {
      console.log(key, person[key])
    }
  script>
  • 详解 Object.defineProperty() & Object.defineProperties()_第1张图片
  • 在使用 Object.defineProperty() 添加属性的时候,可以在配置对象中将 enumerable 的值设置为 true,则使用 Object.defineProperty() 添加的属性可以枚举。
  <script>
    let person = {
      name: 'zs',
      sex: 'male'
    }
    // 向person对象中新添加一个age属性
    Object.defineProperty(person, 'age', {
      value: 18,
      // enumerable 控制属性是否可以枚举,
      // 默认值为 false
      enumerable: true
    })
    console.log(person)
    console.log(Object.keys(person))
    for (let key in person) {
      console.log(key, person[key])
    }
  script>
  • 详解 Object.defineProperty() & Object.defineProperties()_第2张图片

描述指定属性是否可修改 writable

  • 默认情况下,使用 Object.defineProperty() 添加的属性的值是不可以修改的。
  • 要使 Object.defineProperty() 添加的属性值可以修改,在添加属性时,配置对象的 writable 的值设置为 true,使用 Object.defineProperty() 添加的属性值可以修改。
  <script>
    let person = {
      name: 'zs',
      sex: 'male'
    }
    Object.defineProperty(person, 'age', {
      value: 18,
      enumerable: true,
      // 控制属性值是否可以被修改,
      // 默认值为 false
      writable: true
    })

  script>
  • 详解 Object.defineProperty() & Object.defineProperties()_第3张图片

描述指定属性是否可删除 configurable

  • 默认情况下,使用 Object.defineProperty() 添加的属性的值是不可以删除的。
  • 详解 Object.defineProperty() & Object.defineProperties()_第4张图片
  • 要使 Object.defineProperty() 添加的属性值可以删除,在添加属性时,配置对象的 configurable 的值设置为 true,使用 Object.defineProperty() 添加的属性值可以删除。
  <script>
    let person = {
      name: 'zs',
      sex: 'male'
    }
    Object.defineProperty(person, 'age', {
      value: 18,
      enumerable: true,
      writable: true,
      // 控制属性是否可以被删除,
      // 默认值为 false
      configurable: true
    })

  script>
  • 详解 Object.defineProperty() & Object.defineProperties()_第5张图片

访问器描述符 get

  • 该描述符的值为一个函数,默认值为 undefined
  • 当访问 Object.defineProperty() 中指定的属性时,将不会传递参数地调用 get 对应的函数,函数的 this 指向调用 Object.defineProperty() 中指定属性的对象。函数的返回值将被用作该属性的值。
<script>
    let person = {
      name: 'zs',
      sex: 'male'
    }
    Object.defineProperty(person, 'age', {
      // 当读取person的age属性的时候,
      // get函数(getter)会被调用,
      // 且函数返回值就是属性age的值
      // get: function() {
      //   console.log('读取age属性')
      //   return number
      // }
      // 简写
      get() {
        console.log('读取age属性')
        console.log(this)
        return 'hello'
      }
    })
  script>   
  • 详解 Object.defineProperty() & Object.defineProperties()_第6张图片

访问器描述符 set

  • 该描述符的值为一个函数,默认值为 undefined
  • 当 Object.defineProperty() 中指定的属性被赋值时,将调用此函数,并带有一个参数(要赋给该属性的值),并将 this 设置为调用 Object.defineProperty() 中指定属性的对象。
<script>
    let person = {
      name: 'zs',
      sex: 'male'
    }
    Object.defineProperty(person, 'age', {
      get() {
        console.log('读取age属性')
        console.log(this);
        return 'hello'
      },
      // 修改person的age属性的时候,
      // set函数(setter)会被调用,
      // 且会收到修改的具体值
      set(value) {
        console.log('修改了age的属性值:', value)
        console.log(this);
      }
    })
  script>   
  • 详解 Object.defineProperty() & Object.defineProperties()_第7张图片

注意点

  • Object.defineProperty() 中指定属性的描述符中,不能同时具有 [value 或 writable] 和 [get 或 set],否则会抛出异常
<script>
  let person = {
    name: 'zs',
    sex: 'male'
  }
  Object.defineProperty(person, 'age', {
    value: 12,
    get() {
      console.log('读取age属性')
      console.log(this);
      return 'hello'
    },
    set(value) {
      console.log('修改了age的属性值:', value)
      console.log(this);
    }
  })
script>  
  • image.png

Object.defineProperties()

  • 该方法用于在一个对象上定义若干个新属性,或者修改若干个对象上已有的属性,并返回修改后的原对象
Object.defineProperties(obj, props)
  • 该方法需要传递两个参数:
    • obj:需要定义新属性或修改属性的对象
    • props:一个对象,其中每个键表示要定义或修改的属性的名称,每个值是描述该属性的对象,在描述该属性的对象中能够配置的描述选项和 Object.defineProperty() 方法中 descriptor 参数一致。
  • 该方法返回传入的对象,该对象指定的属性已被新增或修改
  • 注意,Object.defineProperties() 和 Object.defineProperty() 一样每个定义的新属性或修改的属性的描述符中不能同时具有 value 或 writable 和 get 或 set 键中的任意一个组合,否则会抛出异常。
const obj = {};
Object.defineProperties(obj, {
  property1: {
    value: true,
    writable: true,
  },
  property2: {
    value: "Hello",
    writable: false,
  },
  // 等等……
});

你可能感兴趣的:(前端,javascript,前端,开发语言,js,Object)