Reputation: 173
By callable object I mean an object that's also a function similar to jQuery.
There's plenty of resources for doing this, such as this article.
However problem arise when I try to implement private fields/properties.
Only the method utilizing arguments.callee
appears to work.
new class extends Function {
constructor() {
super('return arguments.callee._call(...arguments)')
}
_call(x) {
console.log("this object is directly callable")
}
#data;
get data() {
return this.#data ??= link();
}
}
But arguments.callee is deprecated and doesn't work in strict mode so it feels dirty doing it this way.
The conventional wisdom is to use a named function, but there appears to be no way to name the function created by the constructor() that I know of.
I could abandon class and private properties altogether and use IIFE to implement private variables but I really like how clean the syntax is with class and private properties and prefer to stick with it if possible.
Upvotes: 0
Views: 100
Reputation: 665475
The approach from my answer to How to extend Function with ES6 classes? works just fine with private class fields:
function ExtensibleFunction(f) {
return Object.setPrototypeOf(f, new.target.prototype);
}
ExtensibleFunction.prototype = Function.prototype;
class Weird extends ExtensibleFunction {
#data;
constructor(data) {
super((...args) => this._call(...args));
this.#data = data;
}
_call(x) {
console.log(`This object is directly callable and has access to ${this.#data}`);
}
get data() {
return this.#data;
}
}
const example = new Weird('example data');
console.log(example.data);
example();
Or like this:
const call = Symbol('call');
function ExtensibleFunction() {
const f = () => f[call]();
return Object.setPrototypeOf(f, new.target.prototype);
}
ExtensibleFunction.prototype = Function.prototype;
class Weird extends ExtensibleFunction {
#data;
constructor(data) {
super();
this.#data = data;
}
[call](x) {
console.log(`This object is directly callable and has access to ${this.#data}`);
}
get data() {
return this.#data;
}
}
const example = new Weird('example data');
console.log(example.data);
example();
Upvotes: 1