skip to Main Content

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

2

Answers


  1. You can’t call this directly, d1 and d2 are Demo instances, I recommend you to look at what happens in the process of new keyword in js, so you can understand, this is the implementation of the call method you described the code

    function Demo1() {
        return function() {
            console.log(1)
        }
    }
    const d1 = new Demo1();
    
    class Demo2 {}
    const d2 = new Demo2();
    
    d1()

    I recommend you take a look at what the new keyword does so you can understand it

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search