Matt
Matt

Reputation: 1570

Can you trap/identify if an object is being "invoked" as a function in runtime?

Given some basic class, such as a logical predicate class here:

const isACat = new Predicate(obj => obj.cat === true);

Is there a way to determine/trap/identify (perhaps via Reflection?) the context under which isACat is being "invoked/evaluated"? By "invoke/evaluate"--because I can't really think of a better word to use right now--I mean something like this:

console.log(isACat(object1));  // being "invoked/evaluated" as a function
console.log(isACat);           // being "invoked/evaluated" as a non-function

I specifically mean this in the "runtime" sense, not in the typeof/instanceof sense.

For the ultimate goal of performing contingent behavior, such as (perhaps via a Proxy) returning a default function if that instance is being "invoked/evaluated" as a function.

Edit: Maybe in more precise terms, is there such a thing as a "default getter" when no further child prop is passed (i.e. isACat, but not isACat[ prop ])?

Upvotes: 0

Views: 76

Answers (2)

geoffrey
geoffrey

Reputation: 2444

I am not seriously suggesting that you do any of the things presented bellow and you will spot their limitation immediately but I thought it was kind of fun to demonstrate.

[{dog: true}, {cat: true}].filter(isACat);// (referenced(), [{cat: true}])

isACat({dog: true}); // (referenced(), false)

let lives = 0;
lives += isACat; // (referenced(), 7)

`Felix ${isACat}` // (referenced(), "Felix is a cat")

The above requires the following, which you could probably generate with a Babel plugin or something (I mean: don't, obviously)

const referenced = (obj) => () => {
  console.log(obj, 'was referenced');
  return obj;
}

const _isACat = obj => obj.cat === true;
 
Object.defineProperty(_isACat, 'toString', {
  value: () => 'is a cat'
});

Object.defineProperty(_isACat, 'valueOf', {
  value: () => 7
});

Object.defineProperty(window, 'isACat', {
  get: referenced(_isACat)
});

I don't know what I like the most about it: deceiving expectations thanks to getters, magical type coercion, or local variables leaking to the global scope. It is pure poetry.

More seriously, I don't think Javascript is the language for this but if for some reason you need meta-programming power, maybe give Clojure a go. You can also use macros with ClojureScript, which compiles to Javascript and has Javascript interop, but there is a runtime/compile time distinction which will limit what you can do.

Upvotes: 1

Bergi
Bergi

Reputation: 664797

No, there is no such thing. You're just accessing a variable, or whatever the reference to your object is stored in, and you get back a reference value. The object itself has no say about this process - it isn't even looked at yet. This is not "invocation" or "evaluation".

Really, if you need something like this, make the invocation explicit, and write isACat() (vs isACat(object) vs isACat.prop()).

Upvotes: 0

Related Questions