In python, you can make an instance become a callable obj, like below shows:
# py code snippet
class Demo:
def __call__(self):
print("Demo's instance callable")
Demo()() # Demo's instance is callable
In js, is there the same feature like shown above?
// js code snippet
function Demo1() {}
const d1 = new Demo1();
class Demo2 {}
const d2 = new Demo2();
// can I make d1 or d2 become a callable instance? like d1() or d2() to run some function logic.
Another question:
What property or feature on Function
or Function.prototype
, make it's instance is callable? Since I cant find any point of it on MDN Function page
You can not do that. But you can achieve something like that...
Here's my recommendation:
// Define your object with as many properties as needed.
const AnyObject =
{
get Myself ()
{
return this;
}
};
// Define a callable function which can't be arrow function if you
// want to use the this keyword pointing to the defined object.
const UnboundCallable = function ()
{
console.log('The value of this.Myself is:', this?.Myself);
}
// Define a bound callable which points the this keyword to itself.
const BoundCallable = UnboundCallable.bind(UnboundCallable);
// Set your defined object as the prototype of the unbound callable.
Reflect.setPrototypeOf(UnboundCallable, AnyObject);
// Set your defined object as the prototype of the bound callable.
Reflect.setPrototypeOf(BoundCallable, AnyObject);
// You'll actually use the BoundCallable which behaves the best like
// you intend it to.
// You can also do this:
class Demo
{
get Myself ()
{
return this;
}
constructor ()
{
const UnboundCallable = function CallableDemoObject ()
{
console.log('The value of this.Myself is:', this?.Myself);
}
const BoundCallable = UnboundCallable.bind(UnboundCallable);
Reflect.setPrototypeOf(UnboundCallable, this);
Reflect.setPrototypeOf(BoundCallable, this);
return BoundCallable;
}
}
///// TESTS /////
const MyDemo = new Demo;
MyDemo();
// Outputs:
// The value of this.Myself is: [object Function]
console.log( MyDemo.Myself );
// Outputs:
// [object Function]
console.log( MyDemo.name );
// Outputs:
// bound CallableDemoObject
console.log( 'MyDemo is instance of Demo?', MyDemo instanceof Demo );
// Outputs:
// MyDemo is instance of Demo? true
console.log( 'MyDemo is instance of Function?', MyDemo instanceof Function );
// Outputs:
// MyDemo is instance of Function? false
console.log( 'Type of MyDemo:', typeof MyDemo );
// Outputs:
// Type of MyDemo: function
console.log( 'UnboundCallable is instanceof Function?', UnboundCallable instanceof Function );
// Outputs:
// UnboundCallable is instanceof Function? false
console.log( 'Type of UnboundCallable:', typeof UnboundCallable );
// Outputs:
// Type of UnboundCallable: function
UnboundCallable();
// Outputs:
// The value of this.Myself is: undefined
// The above happens because the this keyword inside the function is
// the actual context of the variable that reference the function.
// In Node, if in top level then the this keyword will be undefined.
// In any case, it will return anything other than undefined if the
// referenced value in this has Myself.
console.log( UnboundCallable.Myself );
// Outputs:
// [object Function]
// The above happens because even if the function is unbound, its
// prototype is still AnyObject. Myself is a getter that returns
// the this value which points to the function itself.
BoundCallable();
// Outputs:
// The value of this.Myself is: [object Function]
// The above happens because the function is bound and its this
// keyword points to itself. As the function have the AnyObject
// as its prototype, its Myself getter will return this which
// points to the function itself.
console.log( BoundCallable.Myself );
// Outputs:
// [object Function]
// The above happens because even if the function is bound and its
// prototype is still AnyObject. Myself is a getter that returns
// the this value which points to the function itself.
console.log( BoundCallable.name );
// Outputs:
// bound UnboundCallable
You'll actually use the BoundCallable
as your object which behaves the best like you intend it to.
NOTE: As the generated function object prototype is a prototype of an object and not a function, then BoundCallable
and CallableDemoObject
don't pass the test instanceof Function
, but they're still function
in a typeof
statement.