要记住Object.defineProperty可不只有get和set两个属性哦~

属性:

  1. configurable:当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
    默认为false
  2. enumerable:当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中(决定属性是否可遍历)。
    默认为false
  3. 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
    默认为undefined
  4. writable:当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。
    默认为false
  5. getset

configurable有点变态,主要说一下:

var b = Object.creat(null);
Object.defineProperty(b, "a", {
  configurable: true,
  writable: false,
  value: "fuck"
});
  1. 当configurable为true时,表示该属性【可被设置】和【可被删除】。
    被设置的意思是还可以使用defineProperty重新设置。
    被删除的意思可以使用delete b.a 此属性。
  2. 当configurable为false时,有意思地方来了~首先【不可被删除】是肯定的,我们主要讨论一下能否【被设置】。
    此时如果writable为true,那么你可以设置writable和value。writable可以由true改为 false,但是不能由false改为true。
    此时如果writable为false,那么所有行为都不可以再改变了,再调用Object.defineProperty会报错。

总结:
configurable为false时,writable可以由true改为 false,但是不能由false改为true。其他行为都不可以修改。

应用:

先介绍下object.preventExtensions(...):个人觉得这个方法没什么可单独使用的场景。使用该方法之后对象的确是不能拓展了,但是已有属性TMD可被删。

  1. 密封Object.seal()会创建一个密封的对象,这个方法实际上会在一个现有对象上调用object.preventExtensions(...)并把所有现有属性标记为configurable:false。
    所以, 密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以改属性的值)
  2. 冻结Object.freeze()会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(),并把所有现有属性标记为writable: false,这样就无法修改它们的值。你可以深度冻结一个对象,具体方法为,首先这个对象上调用Object.freeze()然后遍历它引用的所有对象,并在这些对象上调用Object.freeze()

补充:
我们平时使用var a = {}定义的对象,configurable、enumerable、writable默认值都为true,而value为你自己设定的值,如果不设定的话则为undefined。

参考:

  1. MDN
  2. 深入浅出Object.defineProperty()

yzbao
626 声望19 粉丝

Uncaught ReferenceError