Нет, это невозможно.Не существует различия между
const newFoo = new Foo()
newFoo.bar(123);
и
const newFoo = new Foo()
const bar = newFoo.bar;
Function.prototype.call.call(bar, newFoo, 123); // like `bar.call(newFoo, 123)`
// or Reflect.apply(bar, newFoo, [123]);
, т.е. ни newFoo
, ни bar
не могут отличить их "изнутри".Теперь между доступом к свойству и вызовом метода могут произойти произвольные вещи, и во время доступа к свойству вы не можете знать, что произойдет дальше, поэтому вы не можете вызвать исключение преждевременно.Вызов метода может произойти никогда (в newFoo.bar;
), и нет способа распознать это только из newFoo
.
Единственный подход - перехватить все другие обращения к newFoo
и его свойствам,и throw
после вы обнаружили вредную последовательность;возможно, ваш «линтер» проверит последовательность извне после запуска всей программы:
const lint = {
access: 0,
call: 0,
check() {
console.log(this.access == this.call
? "It's ok"
: this.access > this.call
? "method was not called"
: "property was reused");
},
run(fn) {
this.call = this.access = 0;
try {
fn();
} finally {
this.check();
}
}
}
function bar(value) {
lint.call++; lint.check();
return value;
}
class Foo {
get bar() {
lint.check(); lint.access++;
return bar;
}
}
lint.run(() => {
const newFoo = new Foo;
newFoo.bar(123);
});
lint.run(() => {
const newFoo = new Foo;
newFoo.bar;
});
lint.run(() => {
const newFoo = new Foo;
const bar = newFoo.bar;
bar(123);
bar(456);
});
Возможно, лучшим решением будет написать собственный интерпретатор для простых выражений,который позволял бы только вызовы методов.