覆盖使用Object.defineProperty创建的getter / setter

时间:2018-10-03 13:51:51

标签: javascript

我遇到了一个问题,我通过Object.defineProperty添加到对象的属性出现错误。

有问题的错误。

Exception: RangeError: Maximum call stack size exceeded

也许(可能)我的设计不正确,我应该做一些不同的事情。这是我打算使用以下代码进行的操作:

  • 通过工厂函数创建对象P。
  • 将配置对象C传递给工厂以自定义P。
  • 将C作为私有对象存储在P中,并通过Object.defineProperty将其属性附加到P来获取/设置C的值。对于任何给定的P,C可能不同。
  • 当我想覆盖某些C.a的默认get / set方法时,问题就来了

我这样做如下:

// Create P with a custom (non-default) get method.
let C = { a: 1, b: 2, c: 3 };
let P = factory.createObject(C);

const customGetA = function(object, property) {
  return function() {
    if(!object[property])
      object[property] = ' ';
    return object[property];
  };
};

P.customgGetMethod('a', customGetA);

// Looking at object in the console reveals the error mentioned above.

let factory = (function() {
  'use strict';

  this.createObject = function(config) {
    const product = {};

    let C = config;

    // Add default getters/setters to the product, referencing the properties of C.
    for (const property in config) {
      Object.defineProperty(product, property, { 
        get: function() { 
          return C[property];
        },
        set: function(value) {
          C[property] = value;
        },
        configurable: true,
        enumerable: true
      });
    }

    product.customGetMethod = function(property, callback) {
      // Get the property description.
      let descriptor = Object.getOwnPropertyDescriptor(this, property);

      // Assign the custom get method within the callback, binding its values via closure.
      descriptor.get = callback(this, property);

      // Redefine the property with the new get method.
      Object.defineProperty(this, property, descriptor);
    };

    return product;
  };
})();

最后,我希望a能够将自定义数据对象传递给P并将其保持私有状态,并根据该数据动态生成get / set方法,因此我不必获取/设置锅炉板用于 N -属性* M -产品。这可能不是最佳的设计或实现,但是我对如何使用另一种方法感到困惑。

任何其他选择或见识将不胜感激。

1 个答案:

答案 0 :(得分:1)

customGetAP.customgGetMethod('a', customGetA);中创建的getter函数基本上是

function() {
  if(!product.a)
    product.a = ' ';
  return product.a;
}

当我们将其与在factory中创建的默认getter进行比较时

function() { 
  return C.a;
}

我们可以看到,新的查询是在product中查找值,而不是在配置C中查找。在product中查找属性会评估其getter,这是我们已经在使用的函数,递归直到其最终溢出堆栈...

我认为您正在寻找

// Assign the custom get method within the callback, binding its values via closure.
descriptor.get = callback(C, property);
//                        ^

关闭内部配置对象。