简体   繁体   中英

Javascript: How to create a variable that acts like both an object and a function?

In Javascript, I would like to create a variable (primitive or object) that can also be invoked as a function.

The desired result is:

console.log(myVar) // Outputs some variable previously defined
console.log(myVar()) // Outputs the result of some previously defined function

I would like the variable used to be exactly the same. For example, I do not want:

const myVar = () => 1;
myVar.prop = 2;

I have tried overriding both the Object.prototype.toString and Object.prototype.valueOf functions, but each need to be manually invoked:

const myVar = () => 1;
myVar.toString = () => 2;
console.log(myVar + myVar) // This outputs 4, thanks to coercion
console.log(typeof myVar) // Outputs function, want 'number' in this example

My use case for this is the following scenario, where the result of someFunction(payload) acts as both a value and a function.

someFunction(payload)(options) // Result depends upon payload and options, returns a value
someFunction(payload) // Options is not specified, returns a value
someFunction(payload, options) // Would prefer not to use this method

In the desired use case, I'd like someFunction(payload) to act as an alias for someFunction(payload)() . I tried:

const someFunction = payload => {
    const innerFunction = options => {
        // Return value depending on payload and, if it exists, options
    };
    innerFunction.toString = () => innerFunction();
    return innerFunction;
};
console.log(someFunction(payload)(options)) // A value, correct
console.log(someFunction(payload)) // A function, do not want

I also tried using a combination of calling toString and eval (to executed the stringified function) to trigger the toString() , but could not get it to work.

So I'm not entirely sure I understand the "why" of this question, but I am going to give this a shot.

What you could do is create a data type and have it return a default value and then when you use the "new" constructor you could then get access to its values like the function.

So if you see in the below image I created a function and have values that could be used if I constructed the data type, however if I am just invoking the function I am able to return a value instead.

If you use the constructor of the function and create a instance of this data type you can then just manipulate the value directly.

I dont think that totally gets you to where you want, but I am hoping it gets you a little closer.

  function Payload(val, options) { this.innerFunction = () => { console.log(options)} this.value = val return val } console.log(Payload(10, {key:"KEY" })) // print 10 console.log(typeof Payload(10, {key:"KEY" })) // number x = new Payload(10, {key:"KEY" }) x.innerFunction() // returns {key:"KEY" } x.val // returns 10 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM