我遇到了一个问题,即我通过 Object.defineProperty 添加到对象的属性出现错误。
有问题的错误。
Exception: RangeError: Maximum call stack size exceeded
也许(可能(我的设计不正确,我应该做一些不同的事情。这就是我打算用下面的代码做的:
- 通过工厂函数创建对象 P。
- 将配置对象 C 传递给工厂以自定义 P。
- 将 P 中的 C 存储为私有对象,并通过 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;
};
})();
最后,我希望能够将自定义数据对象传递到 P 中并使其保持私有,并根据该数据动态生成 get/set 方法,这样我就不必为N属性 *M产品获取/设置样板。这可能不是最好的设计或实现,但我不知道如何以另一种方式做到这一点。
任何替代方案或见解将不胜感激。
customGetA
在P.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);
// ^
以关闭内部配置对象。