如何在 JS 中为子对象 属性 访问调用 thunk?
How to invoke a thunk for sub-object property access in JS?
有一个 class 个对象,事后我需要将一些函数作为属性惰性添加到这些对象中。因为这些函数必须引用实例变量才能将附加的函数配置为 属性,所以我使用 thunk 来创建函数并转发第一个函数调用。举个简单的例子:
function Foo(val) {
this.val = val;
}
// simulates a library call which returns a complex object with methods
// this library call requires access to some of the object information,
// simulated by passing in `type`
function buildWorkFunction(type) {
var f = function() { return this.val; };
if (type === 'string')
f = function() { return this.val.length; };
f.getType = function() { return type; };
return f;
}
function addProperty(Base, prop) {
var thunk = function() {
// typeof is just a simple example of how buildWorkFunction could
// change based on this.val
this[prop] = buildWorkFunction(typeof this.val);
return this[prop].apply(this, arguments);
};
thunk.getType = function() {
return 'TODO'; // <-- this is the part I need help with
};
Base.prototype[prop] = thunk;
}
// simulates instances existing before the module load
var foo = new Foo('foo');
// runs after user requests a module load, runs from the module
setTimeout(function() {
// adding a module specific property to the non-module model
addProperty(Foo, 'getVal');
console.log(foo.getVal());
console.log(foo.getVal.getType());
// simulates instances created after the module load
var bar = new Foo(17);
console.log(bar.getVal.getType()); // called before thunk - fails
console.log(bar.getVal());
console.log(bar.getVal.getType()); // called after thunk - works
}, 0);
我留下的一个问题是 属性 的值本身具有应用程序代码有时在不调用 属性 本身的情况下引用的属性,就像上面的 f.getType
一样。如何在不先调用 foo.getVal()
的情况下正确地 catch/proxy/forward 调用 foo.getVal.getType()
?附加属性的名称定义明确并且可以共享 - 但我看不到如何访问正确的 this
或来自它们的数据。
How can I properly catch/proxy calls such as foo.getVal.getType()
? If foo.getVal()
isn't called first, I can't see how to access the correct this or the data from them.
您可以使用与之前相同的方法,但在 属性 getter 级别而不是方法调用级别。这使得延迟创建任意实例属性成为可能:
function addProperty(Base, prop) {
Object.defineProperty(Base.prototype, prop, {
get: function thunk() {
var propertyValue = buildWorkFunction(typeof this.val);
// ^^^^^^^^^^^^^^^ access the instance here
// overwrite (shadow) the prototype getter:
Object.defineProperty(this, prop, {
value: propertyValue,
writable: true,
enumerable: true,
configurable: true
});
return this[prop];
},
enumerable: true, // dunno
configurable: true
});
}
有一个 class 个对象,事后我需要将一些函数作为属性惰性添加到这些对象中。因为这些函数必须引用实例变量才能将附加的函数配置为 属性,所以我使用 thunk 来创建函数并转发第一个函数调用。举个简单的例子:
function Foo(val) {
this.val = val;
}
// simulates a library call which returns a complex object with methods
// this library call requires access to some of the object information,
// simulated by passing in `type`
function buildWorkFunction(type) {
var f = function() { return this.val; };
if (type === 'string')
f = function() { return this.val.length; };
f.getType = function() { return type; };
return f;
}
function addProperty(Base, prop) {
var thunk = function() {
// typeof is just a simple example of how buildWorkFunction could
// change based on this.val
this[prop] = buildWorkFunction(typeof this.val);
return this[prop].apply(this, arguments);
};
thunk.getType = function() {
return 'TODO'; // <-- this is the part I need help with
};
Base.prototype[prop] = thunk;
}
// simulates instances existing before the module load
var foo = new Foo('foo');
// runs after user requests a module load, runs from the module
setTimeout(function() {
// adding a module specific property to the non-module model
addProperty(Foo, 'getVal');
console.log(foo.getVal());
console.log(foo.getVal.getType());
// simulates instances created after the module load
var bar = new Foo(17);
console.log(bar.getVal.getType()); // called before thunk - fails
console.log(bar.getVal());
console.log(bar.getVal.getType()); // called after thunk - works
}, 0);
我留下的一个问题是 属性 的值本身具有应用程序代码有时在不调用 属性 本身的情况下引用的属性,就像上面的 f.getType
一样。如何在不先调用 foo.getVal()
的情况下正确地 catch/proxy/forward 调用 foo.getVal.getType()
?附加属性的名称定义明确并且可以共享 - 但我看不到如何访问正确的 this
或来自它们的数据。
How can I properly catch/proxy calls such as
foo.getVal.getType()
? Iffoo.getVal()
isn't called first, I can't see how to access the correct this or the data from them.
您可以使用与之前相同的方法,但在 属性 getter 级别而不是方法调用级别。这使得延迟创建任意实例属性成为可能:
function addProperty(Base, prop) {
Object.defineProperty(Base.prototype, prop, {
get: function thunk() {
var propertyValue = buildWorkFunction(typeof this.val);
// ^^^^^^^^^^^^^^^ access the instance here
// overwrite (shadow) the prototype getter:
Object.defineProperty(this, prop, {
value: propertyValue,
writable: true,
enumerable: true,
configurable: true
});
return this[prop];
},
enumerable: true, // dunno
configurable: true
});
}