运行 调用任何其他 class 函数时的函数
Run a function when any other class function is called
我有一个 es6 class 有超过 100 个功能。
我添加了一个新函数,每次调用任何其他函数时我都必须 运行。
我找到了很多解决方案,但没有人解决我的问题...
我知道我可以将此调用添加到每个函数,但我将以代码重复和所有函数的大量工作结束。
那就是我到目前为止所做的:
return class Test {
constructor () {}
addedFN() {
console.log('FN');
}
A() {
this.addedFN();
console.log('A');
}
B() {
this.addedFN();
console.log('B');
}
C() {
this.addedFN();
console.log('C');
}
...
}
正如我们在这种方法中看到的那样,我有很多我想避免的代码重复...
另外,先调用新函数再在内部调用下一个函数的方案也不行,因为所有的函数在应用中很多地方都要用到。
我还尝试 运行 构造函数中的以下代码,但这是一个糟糕的解决方案,因为我的 class 被调用了很多次,然后这段代码每次都会 运行 :
for(const key of Object.getOwnPropertyNames(Test.prototype)) {
const old = Test.prototype[key];
Test.prototype[key] = function(...args) {
addedFN(...args);
old.call(this, ...args);
};
}
不要运行在构造函数中,运行在class声明之后
此外,该解决方案将导致过多的递归,因为它也适用于 addedFn
,后者将调用 addedFn
,后者将调用 addedFn
... 等等,直到您的浏览器抛出“太多递归”错误
所以你也不想把它应用到 addedFn
在下面的代码中,我也没有将它应用于 constructor
...但是,即使我这样做了,它也不会在构造对象时调用 addedFn
,所以,为了更清楚,我明确地不触及构造函数
class Test {
constructor(y) {
this.y = y
}
fun1(x) {
console.log('I am fun1', x, this.y);
}
fun2() {
console.log('I am fun2');
}
addedFn(...x) {
console.log('added function', ...x);
}
}
Object.getOwnPropertyNames(Test.prototype).forEach(f => {
if (f !== 'constructor' && f !== 'addedFn' && typeof Test.prototype[f] === 'function') {
const old = Test.prototype[f];
Test.prototype[f] = function(...args) {
this.addedFn(...args);
return old.apply(this, args);
}
}
})
let c = new Test('works');
c.fun1(1,2,3)
注意:您还应该测试 Test.prototype[f]
是否是一个函数 - 除非您的 class 只有函数
这可能是 Proxy
的一个很好的用途,可以透明地更改您的对象而无需实际更改对象,只需将其包装在代理中即可。
一个get
trap can check if you are accessing a method and then dynamically wrap it into a proxy with an apply
trap.
class Test {
A() { console.log('A'); }
B() { console.log('B'); }
C() { console.log('C'); }
get X() { return 1; }
Y = 2;
}
function addedFN() { console.log('FN'); }
const loggingHandler = {
apply() {
addedFN();
return Reflect.apply(...arguments);
}
};
const wrapMethods = {
get() {
const result = Reflect.get(...arguments);
if (typeof result === "function")
return new Proxy(result, loggingHandler);
return result;
}
};
const test = new Test();
const foo = new Proxy(test, wrapMethods);
foo.A();
foo.B();
foo.C();
console.log(foo.X);
console.log(foo.Y);
.as-console-wrapper { max-height: 100% !important; }
该方法可以被概括为接受不同的方法修饰符并将它们缓存在 WeakMap
class Test {
A() { console.log('A'); }
B() { console.log('B'); }
C() { console.log('C'); }
get X() { return 1; }
Y = 2;
}
function addedFN() { console.log('FN'); }
const noop = () => {};
const wrapFunction = ({before = noop, after = noop}) => ({
apply() {
before();
const result = Reflect.apply(...arguments);
after();
return result;
}
});
const wrapMethods = handler => ({
_cache: new WeakMap(),
get() {
const result = Reflect.get(...arguments);
if (typeof result === "function") {
if (!this._cache.has(result))
this._cache.set(result, new Proxy(result, handler));
return this._cache.get(result);
}
return result;
}
});
const loggingHandler = wrapFunction({before: addedFN});
const test = new Test();
const foo = new Proxy(test, wrapMethods(loggingHandler));
foo.A();
foo.B();
foo.C();
console.log(foo.X);
console.log(foo.Y);
我有一个 es6 class 有超过 100 个功能。
我添加了一个新函数,每次调用任何其他函数时我都必须 运行。
我找到了很多解决方案,但没有人解决我的问题...
我知道我可以将此调用添加到每个函数,但我将以代码重复和所有函数的大量工作结束。
那就是我到目前为止所做的:
return class Test {
constructor () {}
addedFN() {
console.log('FN');
}
A() {
this.addedFN();
console.log('A');
}
B() {
this.addedFN();
console.log('B');
}
C() {
this.addedFN();
console.log('C');
}
...
}
正如我们在这种方法中看到的那样,我有很多我想避免的代码重复...
另外,先调用新函数再在内部调用下一个函数的方案也不行,因为所有的函数在应用中很多地方都要用到。
我还尝试 运行 构造函数中的以下代码,但这是一个糟糕的解决方案,因为我的 class 被调用了很多次,然后这段代码每次都会 运行 :
for(const key of Object.getOwnPropertyNames(Test.prototype)) {
const old = Test.prototype[key];
Test.prototype[key] = function(...args) {
addedFN(...args);
old.call(this, ...args);
};
}
不要运行在构造函数中,运行在class声明之后
此外,该解决方案将导致过多的递归,因为它也适用于 addedFn
,后者将调用 addedFn
,后者将调用 addedFn
... 等等,直到您的浏览器抛出“太多递归”错误
所以你也不想把它应用到 addedFn
在下面的代码中,我也没有将它应用于 constructor
...但是,即使我这样做了,它也不会在构造对象时调用 addedFn
,所以,为了更清楚,我明确地不触及构造函数
class Test {
constructor(y) {
this.y = y
}
fun1(x) {
console.log('I am fun1', x, this.y);
}
fun2() {
console.log('I am fun2');
}
addedFn(...x) {
console.log('added function', ...x);
}
}
Object.getOwnPropertyNames(Test.prototype).forEach(f => {
if (f !== 'constructor' && f !== 'addedFn' && typeof Test.prototype[f] === 'function') {
const old = Test.prototype[f];
Test.prototype[f] = function(...args) {
this.addedFn(...args);
return old.apply(this, args);
}
}
})
let c = new Test('works');
c.fun1(1,2,3)
注意:您还应该测试 Test.prototype[f]
是否是一个函数 - 除非您的 class 只有函数
这可能是 Proxy
的一个很好的用途,可以透明地更改您的对象而无需实际更改对象,只需将其包装在代理中即可。
一个get
trap can check if you are accessing a method and then dynamically wrap it into a proxy with an apply
trap.
class Test {
A() { console.log('A'); }
B() { console.log('B'); }
C() { console.log('C'); }
get X() { return 1; }
Y = 2;
}
function addedFN() { console.log('FN'); }
const loggingHandler = {
apply() {
addedFN();
return Reflect.apply(...arguments);
}
};
const wrapMethods = {
get() {
const result = Reflect.get(...arguments);
if (typeof result === "function")
return new Proxy(result, loggingHandler);
return result;
}
};
const test = new Test();
const foo = new Proxy(test, wrapMethods);
foo.A();
foo.B();
foo.C();
console.log(foo.X);
console.log(foo.Y);
.as-console-wrapper { max-height: 100% !important; }
该方法可以被概括为接受不同的方法修饰符并将它们缓存在 WeakMap
class Test {
A() { console.log('A'); }
B() { console.log('B'); }
C() { console.log('C'); }
get X() { return 1; }
Y = 2;
}
function addedFN() { console.log('FN'); }
const noop = () => {};
const wrapFunction = ({before = noop, after = noop}) => ({
apply() {
before();
const result = Reflect.apply(...arguments);
after();
return result;
}
});
const wrapMethods = handler => ({
_cache: new WeakMap(),
get() {
const result = Reflect.get(...arguments);
if (typeof result === "function") {
if (!this._cache.has(result))
this._cache.set(result, new Proxy(result, handler));
return this._cache.get(result);
}
return result;
}
});
const loggingHandler = wrapFunction({before: addedFN});
const test = new Test();
const foo = new Proxy(test, wrapMethods(loggingHandler));
foo.A();
foo.B();
foo.C();
console.log(foo.X);
console.log(foo.Y);