'How to access a function defined as key of an object from within another function defined as key of same object in JS

Given below code, I need to reuse functionality from innerFunc1 and innerFunc2 in innerfunc3, but I am not sure, how innerFunc1 and innerFunc2 can be accessed inside innerfunc3, because those are not even defined at the time. Also, I am wondering, is there a better pattern to achieve this functionality?

const outerFunc = () => ({
    innerFunc1: () => {
        console.log("Inner function 1");
    },
    innerFunc2: () => {
        console.log("Inner function 2");
    },
    innerFunc3: () => {
        innerFunc1();
        innerFunc2();
        console.log("Inner function 3");
    }
});

const func = outerFunc();
func.innerFunc3();

Expected behaviour

Inner function 1
Inner function 2
Inner function 3

But apparent output is ReferenceError: innerFunc1 is not defined

Update:

It occurred to me that desired output can be achieved using below code

const outerFunc = () => ({
    innerFunc1: () => {
        console.log("Inner function 1");
    },
    innerFunc2: () => {
        console.log("Inner function 2");
    },
    innerFunc3: () => {
        const func = outerFunc();
        func.innerFunc1();
        func.innerFunc2();
        console.log("Inner function 3");
    }
});

const func = outerFunc();
func.innerFunc3();

But, is it the right pattern to use?



Solution 1:[1]

ES Classes solution

class + this keyword

class Func {
    innerFunc1 = () => {
        console.log("Inner function 1");
    }
    innerFunc2 = () => {
        console.log("Inner function 2");
    }
    innerFunc3 = () => {
        this.innerFunc1();
        this.innerFunc2();
        console.log("Inner function 3");
    }
}

const func = new Func();
func.innerFunc3();

BUT, as @Sergey pointed out right

Assigning functions to class properties is not considered to be a good practice since it will duplicate this logic each time an instance is created. Instead it should be defined as a regular method and thus one method will be shared with N instances through the prototype

Solution without classes

factory function + this keyword

const outerFunc = () => ({
    innerFunc1: function() {
        console.log("Inner function 1");
    },
    innerFunc2: function() {
        console.log("Inner function 2");
    },
    innerFunc3: function() {
        this.innerFunc1();
        this.innerFunc2();
        console.log("Inner function 3");
    }
});

const func = outerFunc();
func.innerFunc3();

It works because of the normal vs arrow function difference when working with function invocation context.

In case of a normal function this will be a reference to a func, because it is determined on call and the call happens on func object.

In case of an arrow function this will be undefined, because an arrow function infers it's context on it's creation when the object is not yet instantiated.

Solution 2:[2]

If for whatever reason you must use arrow functions instead of regular functions. You can use a closure to store the object.

const outerFunc = () => {
    let obj = {
        innerFunc1: () => {
            console.log("Inner function 1");
        },
        innerFunc2: () => {
            console.log("Inner function 2");
        },
        innerFunc3: () => {
            obj.innerFunc1();
            obj.innerFunc2();
            console.log("Inner function 3");
       }
    };
    return obj;
});

Solution 3:[3]

Another solution with keeping use of arrow functions would be to define functions as variables and return as an object at the end. This will also eliminate the need to use this keyword for other function invocations.

const outerFunc = () => {
    const innerFunc1 = () => {
        console.log("Inner function 1");
    };

    const innerFunc2 = () => {
        console.log("Inner function 2");
    };

    const innerFunc3 = () => {
        innerFunc1();
        innerFunc2();
        console.log("Inner function 3");
    };
    return {
        innerFunc1,
        innerFunc2,
        innerFunc3
    };
};

const func = outerFunc();
func.innerFunc3();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 MinusFour
Solution 3 manmohanshah