详谈Object.defineProperty

概述

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性,并返回这个对象。

语法

Object.defineProperty(obj,prop,descriptor)

参数

  • obj 需要定义属性的对象。
  • prop 需定义或修改的属性的名字。
  • descriptor 将被定义或修改的属性的描述符。

属性描述符

属性 默认值 说明
configurable false 描述属性是否可以被删除,默认为 false ; 具备 数据描述符 和 存取描述符
enumerable false 描述属性是否可以被for…in或Object.keys枚举,默认为 false ; 具备 数据描述符 和 存取描述符
writable false 描述属性是否可以修改,默认为 false ; 具备 数据描述符
value undefined 属性值,默认为undefined ; 具备 数据描述符
get undefined 当访问属性时触发该方法,默认为undefined ; 具备 存取描述符
set undefined 当属性被修改时触发该方法,默认为undefined; 具备 存取描述符

js对象中属性描述符号有两种形式: 数据描述符和存取描述符:

数据描述符

拥有可写或不可写值的属性,可选键值如下:

  • configurable
  • enumerable
  • writable
  • value

举个例子:

  var a={};
    Object.defineProperty(a, "b", {
      configurable: false, // 不可删除
      enumerable: false,// 不可通过for in 枚举
      writable: false, // 不可通过等号赋值改写
      value: 8  //属性值
    })
    console.log(a.b);//8
    console.log(Object.keys(a));// []
    a.b=1; //报错  Uncaught TypeError: Cannot assign to read only property 'b' of object '#<Object>'
    delete a.b //报错 Uncaught TypeError: Cannot delete property 'b' of #<Object>

存取描述符

由一对getter-setter函数功能来描述的属性,可选键值如下:

  • configurable
  • enumerable
  • get
  • set

举个例子:

  var b={},val='7';
  Object.defineProperty(b, "a", {
    configurable: false, // 不可删除
    enumerable: false,// 不可通过for in 枚举
    get: function () {
      return val
    },
    set: function (newVal) {
      val = newVal
    }
  })
  console.log(b.a);// 7
  console.log(Object.keys(b));//[]
  b.a=1;
  console.log(b.a);// 1
  delete b.a ;//报错 Uncaught TypeError: Cannot delete property 'a' of #<Object>

因为JS的数据描述符和存取描述符只能选取一种规则,所以在 descriptor 中 如果设置了 set 或 get, 就不能设置 writable 和 value 中的任何一个,否则报如下错误:

    Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object> at Function.defineProperty