Skip to content

Instantly share code, notes, and snippets.

@rauschma
Created February 11, 2025 13:59
Show Gist options
  • Save rauschma/99c4c15259671acb47b651e0d1da17aa to your computer and use it in GitHub Desktop.
Save rauschma/99c4c15259671acb47b651e0d1da17aa to your computer and use it in GitHub Desktop.
// Experiment: I’m not sure if I would use this myself.
const call = Symbol('call');
class Callable {
constructor() {
// Can’t use .bind() here. Not sure why. Maybe the result doesn’t
// interact well with Object.setPrototypeOf().
const _this = (...args) => new.target.prototype[call].call(_this, ...args);
Object.setPrototypeOf(_this, new.target.prototype);
return _this;
}
}
class Frobnicator extends Callable {
constructor(x, y) {
super();
this.x = x;
this.y = y;
}
[call](z) {
return z * this._product;
}
// Can’t use private slots (which can only be accessed via original instance)
get _product() {
return this.x * this.y;
}
}
const ten = new Frobnicator(2, 5);
console.log(ten(3), "thirty");
@ziadkh0
Copy link

ziadkh0 commented Feb 11, 2025

Looks like Callable can also be implemented as:

class Callable extends Function {
  constructor() {
    const _this = super('return this(...arguments)').bind((...args) => new.target.prototype[call].apply(_this, args));
    return _this;
  }
}

Any downsides?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment