admin管理员组文章数量:1431936
I have a class that I'd like to apply a proxy to, observing method calls and constructor calls:
Calculator.js
class Calc {
constructor(){}
add(a, b) {
return a+b;
}
minus(a, b) {
return a-b;
}
}
module.exports = Calc;
index.js
const Calculator = require('./src/Calculator');
const CalculatorLogger = {
construct: function(target, args, newTarget) {
console.log('Object instantiated');
return new target(...args);
},
apply: function(target, thisArg, argumentsList) {
console.log('Method called');
}
}
const LoggedCalculator = new Proxy(Calculator, CalculatorLogger);
const calculator = new LoggedCalculator();
console.log(calculator.add(1,2));
When this is called, I would expect for the output to be:
Object instantiated
Method called
however, the apply is not being called, I assume that this is because I am attaching the Proxy to the Calculator class, but not the instantiated object, and so doesn't know about the apply
trap.
How can i build an all enpassing Proxy to "observe" on method calls and constructor calls.
I have a class that I'd like to apply a proxy to, observing method calls and constructor calls:
Calculator.js
class Calc {
constructor(){}
add(a, b) {
return a+b;
}
minus(a, b) {
return a-b;
}
}
module.exports = Calc;
index.js
const Calculator = require('./src/Calculator');
const CalculatorLogger = {
construct: function(target, args, newTarget) {
console.log('Object instantiated');
return new target(...args);
},
apply: function(target, thisArg, argumentsList) {
console.log('Method called');
}
}
const LoggedCalculator = new Proxy(Calculator, CalculatorLogger);
const calculator = new LoggedCalculator();
console.log(calculator.add(1,2));
When this is called, I would expect for the output to be:
Object instantiated
Method called
however, the apply is not being called, I assume that this is because I am attaching the Proxy to the Calculator class, but not the instantiated object, and so doesn't know about the apply
trap.
How can i build an all enpassing Proxy to "observe" on method calls and constructor calls.
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Jun 13, 2018 at 16:52 JaredeJarede 3,4986 gold badges47 silver badges75 bronze badges 2-
You're not even applying the
calculator
object (it's not a function). You're applying theadd
method. – Bergi Commented Jun 13, 2018 at 17:31 -
1
FYI, you should always try to use
Reflect
where possible in proxy handlers, so here you'd wantReflect.construct
rather thannew target
. – loganfsmyth Commented Jun 13, 2018 at 17:34
2 Answers
Reset to default 5I assume that this is because I am attaching the Proxy to the Calculator class, but not the instantiated object, and so doesn't know about the apply trap.
You are totally right, proxies act upon objects, so it won't call apply unless a function property of the Calculator
class is called, as follows:
class Calculator {
constructor() {
this.x = 1;
}
instanceFunction() {
console.log('Instance function called');
}
static staticFun() {
console.log('Static Function called');
}
}
const calcHandler = {
construct(target, args) {
console.log('Calculator constructor called');
return new target(...args);
},
apply: function(target, thisArg, argumentsList) {
console.log('Function called');
return target(...argumentsList);
}
};
Calculator = new Proxy(Calculator, calcHandler);
Calculator.staticFun();
const obj = new Calculator();
obj.instanceFunction();
With that clear, what you could do to wrap an instance of Calculator
with a proxy could be:
- Have the class proxy to proxify instances on
construct
:
const CalculatorInstanceHandler = {
apply(target, thisArg, args) {
console.log('Function called');
return target(...args);
}
}
const CalculatorClassHandler = {
construct(target, args) {
const instance = new target(...args);
return new Proxy(instance, CalculatorInstanceHandler);
}
}
- Have a factory function in the
Calculator
class in order to create proxified instances:
const CalculatorInstanceHandler = {
apply(target, thisArg, args) {
return target(...args);
}
};
class Calculator {
static getNewCalculator() {
const instance = new Calculator();
return new Proxy(instance, CalculatorInstanceHandler);
}
}
Instead of using handler.apply()
on the class, modify what handler.construct()
returns, adding a Proxy to that instead.
class originalClass {
constructor() {
this.c = 1;
}
add(a, b) {
return a + b + this.c;
}
}
const proxiedClass = new Proxy(originalClass, {
construct(target, args) {
console.log("constructor of originalClass called.");
return new Proxy(new target(...args), {
get(target, prop, receiver) {
console.log(prop + " accessed on an instance of originalClass");
const val = target[prop];
if (typeof target[prop] === "function") {
console.log(prop + " was a function");
return function(...args) {
console.log(prop + "() called");
return val.apply(this, args);
};
} else {
return val;
}
}
});
}
});
const proxiedInstance = new proxiedClass();
console.log(proxiedInstance.add(1, 2));
There's 2 proxies in play here:
- A proxy to observe constructor calls, and wrap any instances created by that constructor with...
- ...a proxy to observe property accesses, and log when those properties are functions. It will also wrap any functions, so it can observe calls to that function.
本文标签: ecmascript 6mixing constructor and apply traps on the Javascript Proxy objectStack Overflow
版权声明:本文标题:ecmascript 6 - mixing constructor and apply traps on the Javascript Proxy object - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745586387a2664932.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论