javascriptnamespacesnested-functionjavascript-namespaces

Nested functions error, Unexpected token ':', Cannot read property of undefined


I want to make my code more clear, that the reason i am trying to learn namespaces or nested functions. I've read about them in several places and as i understood 'Revealing Module' is the best option. So i tried to copy second example from this post namespace.

At first, i got the error when trying to return object with two methods: Unexpected token ':'. When i tried to return one method instead of 2, i got the Cannot read property of undefined error when tried to call applyEvents of expandableElements object.

let expandableElements = 
(
    function() 
    {
        // All expandable elements
        let expands = document.querySelectorAll(".expand-icon");

        // Apply events to all .expand-icon elements
        function applyExpandEvents()
        {
            for(let i = 0; i < expands.length; i++)
            {
                expands[i].addEventListener("click", expandList);
            }

            // Expand method
            function expandList() 
            {
                this.classList.toggle("active");
                let content = this.previousElementSibling;

                if (content.style.maxHeight)
                {
                    content.style.padding = "0";

                    content.style.maxHeight = null;
                } 
                else 
                {
                    content.style.padding = "1rem";
                    content.style.paddingBottom = "0.5rem";

                    content.style.maxHeight = content.scrollHeight + 20 + "px";
                } 
            }
        }


        // Close all expanded lists
        function closeAllExpands()
        {
            for(let i = 0; i < expands.length; i++)
            {
                let expand = expands[i];

                if(expand.classList.contains("active"))
                {
                    expand.classList.toggle("active");

                    expand.previousSibling.style.padding = "0";
                    expand.previousSibling.style.maxHeight = null;
                }
            }
        }

        return 
        {
            applyEvents : applyExpandEvents,
            closeAll    : closeAllExpands // Unexpected token ':'
        };
    }
)();

expandableElements.applyEvents(); // If remove closeAll from return, then'Cannot read property applyEvents of undefined'

Solution

  • The return and the JSON must be on the same line. As soon as the return line is executed, the control is handed over to the caller (with undefined) and the JSON line never get executed.

    do it like this:

    ...
            return {
                applyEvents : applyExpandEvents,
                closeAll    : closeAllExpands // Unexpected token ':'
            };
    

    Detailed Explanation from MDN docs about return:

    The return statement is affected by automatic semicolon insertion (ASI). No line terminator is allowed between the return keyword and the expression.

    return
    a + b;
    

    is transformed by ASI into:

    return; 
    a + b;