你什么时候使用Object.defineProperty()

And*_*old 61 javascript ecmascript-5

我想知道什么时候应该使用

Object.defineProperty
Run Code Online (Sandbox Code Playgroud)

为对象创建新属性.我知道我能够设置类似的东西

enumerable: false
Run Code Online (Sandbox Code Playgroud)

但你什么时候需要这个呢?如果你只是设置一个属性

myObject.myprop = 5;
Run Code Online (Sandbox Code Playgroud)

它的描述符都设置为true,对吧?当你们使用.defineProperty()的相当冗长的调用以及出于什么原因时,我实际上更好奇.

Rob*_*b W 39

Object.defineProperty主要用于设置具有特定属性描述符的属性(例如只读(常量)),可枚举性(不显示for (.. in ..)循环中的属性,getter,setter).

"use strict";
var myObj = {}; // Create object
// Set property (+descriptor)
Object.defineProperty(myObj, 'myprop', {
    value: 5,
    writable: false
});
console.log(myObj.myprop);// 5
myObj.myprop = 1;         // In strict mode: TypeError: myObj.myprop is read-only
Run Code Online (Sandbox Code Playgroud)

此方法Object使用属性扩展原型.仅定义了getter,并将可枚举性设置为false.

Object.defineProperty(Object.prototype, '__CLASS__', {
    get: function() {
        return Object.prototype.toString.call(this);
    },
    enumerable: false // = Default
});
Object.keys({});           // []
console.log([].__CLASS__); // "[object Array]"
Run Code Online (Sandbox Code Playgroud)

  • @Andre:如果你没有看到它们的用例,那么你不需要它们......当你需要它们时,你会知道;) (11认同)

Pas*_*ius 23

像"可枚举"这样的功能在我的体验中很少使用.主要用例是计算属性:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

Object.defineProperty(myObj, 'area', {
    get: function() {
        return this.width*this.height;
    }
});
console.log(myObj.area);
Run Code Online (Sandbox Code Playgroud)

  • 主要用途是,您可以使用包含自定义逻辑的getter/setter定义单个属性,而不是使用两个单独的函数(例如:getFoo(),setFoo()),然后在单个函数上使用标准赋值运算符成员(例如:x = myObj.Foo或myObj.Foo = x).这使得您的代码更简单,并且在您想要在序列化为JSON时阻止发出值时也很有用.(例如:您的对象有一堆特定于UI的属性,您不希望通过线路发送...)总而言之,这有助于JS更严格地遵循标准的OO原则 (12认同)
  • 该函数完全有效,但可能存在您更喜欢属性而不是函数的用例. (8认同)
  • 我只是不了解提供计算属性的用例,而不是简单地使它成为一个函数.例如myObj.area = function(){return this.width*this.height; } (2认同)

Ger*_*son 13

使用Object.defineProperty的一个很好的理由是,它允许您将对象中的函数作为计算属性循环,该函数执行函数而不是返回函数的主体.

例如:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

Object.defineProperty(myObj, 'area', {
    get: function() {
        return this.width*this.height;
    },
    enumerable: true
});

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}
//width -> 20, height -> 20, area -> 400
Run Code Online (Sandbox Code Playgroud)

将该函数作为属性添加到对象文字中:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

myObj.area = function() {
       return this.width*this.height;
    };

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}
// width -> 20, height -> 20, area -> function() { return this.width*this.height;}
Run Code Online (Sandbox Code Playgroud)

确保将enumerable属性设置为true以循环它.


Dan*_*ger 6

例如,这就是 Vue.js 跟踪data对象变化的方式

当您将普通 JavaScript 对象作为其data选项传递给 Vue 实例时,Vue 将遍历其所有属性并将它们转换为getter/settersusing Object.defineProperty。这是一个仅限 ES5 且不可调整的功能,这就是 Vue 不支持 IE8 及更低版本的原因。

getter/setter 对用户是不可见的,但在幕后,它们使 Vue 能够在访问或修改属性时执行依赖项跟踪和更改通知。

[...]

请记住,即使是 Vue.js 的超薄和基本版本也会使用更多的东西Object.defineProperty,但主要功能来自它:

Vue.js 的反应周期

在这里你可以看到一篇文章,其中作者实现了 Vue.js 之类的最小 PoC 版本:https ://medium.com/js-dojo/understand-vue-reactivity-implementation-step-by-step-599c3d51cd6c

这里有一个演讲(西班牙语),演讲者在解释 Vue.js 中的反应性时构建了类似的东西:https : //www.youtube.com/watch? v = axXwWU-L7RM


Wil*_*een 5

概括:

在 Javascript 中,对象是键值对的集合。 Object.defineProperty()是一个可以在对象上定义新属性并可以设置属性的以下属性的函数:

  • value <any>:与键关联的值
  • writable <boolean>如果 writable 设置为 ,则true可以通过为其分配新值来更新该属性。如果设置为false您无法更改该值。
  • enumerable <boolean>如果 enumerable 设置为trueProperty 可以通过循环访问for..in。此外,唯一返回的可枚举属性键是Object.keys()
  • configurable <boolean>如果可配置设置为false您无法更改属性属性(值/可写/可枚举/可配置),而且由于您无法更改值,因此无法使用运算符删除它delete

例子:

let obj = {};


Object.defineProperty(obj, 'prop1', {
      value: 1,
      writable: false,
      enumerable: false,
      configurable: false
});   // create a new property (key=prop1, value=1)


Object.defineProperty(obj, 'prop2', {
      value: 2,
      writable: true,
      enumerable: true,
      configurable: true
});  // create a new property (key=prop2, value=2)


console.log(obj.prop1, obj.prop2); // both props exists

for(const props in obj) {
  console.log(props);
  // only logs prop2 because writable is true in prop2 and false in prop1
}


obj.prop1 = 100;
obj.prop2 = 100;
console.log(obj.prop1, obj.prop2);
// only prop2 is changed because prop2 is writable, prop1 is not


delete obj.prop1;
delete obj.prop2;

console.log(obj.prop1, obj.prop2);
// only prop2 is deleted because prop2 is configurable and prop1 is not
Run Code Online (Sandbox Code Playgroud)


小智 5

Object.defineProperty 防止您意外地为其原型链中的某个键赋值。使用此方法,您仅分配给特定的对象级别(而不分配给原型链中的任何键)。

例如:有一个像这样的对象{key1: value1, key2: value2},你不确切地知道它的原型链,或者你错误地错过了它,并且原型链中的某处有一些属性“颜色”,那么 -

使用点(.) 赋值 -

此操作会将值分配给原型链中的键“color”(如果键存在于某处),您将发现没有更改的对象为 。obj.color='蓝色'; // obj 保持与 {key1: value1, key2: value2} 相同

使用 Object.defineProperty 方法-

Object.defineProperty(obj, 'color', {
  value: 'blue'
});
Run Code Online (Sandbox Code Playgroud)

// 现在 obj 看起来像{key1: value1, key2: value2, color: 'blue'}. 它将属性添加到同一级别。然后您可以使用 method 安全地进行迭代Object.hasOwnProperty()