如何在 JavaScript 中使用带嵌套、揭示模块模式的链接?

How to use Chaining with Nested, Revealing Module Patterns in JavaScript?

我正在努力了解结合在一起的几个 JS 模式:揭示模块模式链接模式.

理想情况下,我希望能够从单个初始化函数调用多个方法,如下所示:

components
    .loader()
    .menu()
    .toolbar();

只要我公开定义的任何方法都可以正常工作return this;

然而,当我需要嵌套显示模块模式以公开在初始化之外调用的更深层方法时,事情开始出错,如下所示:

components
    .menu
        .close();

这样做的问题是 menu 不再是 returns components,而是 returns 它是子方法,这意味着它在此时打破了链。这是一个“完整”的例子来说明我试图实现的目标:

var components = function () {

    var loader = function () {
        console.log("components.loader initialisation");

        return this;
    }

    var menu = function () {
        console.log("components.menu initialisation");

        var open = function () {
            console.log("components.menu.open");

            return this;
        }
        var close = function () {
            console.log("components.menu.close");

            return this;
        }

        return {
            open: open,
            close: close
        }
    }();

    var toolbar = function () {
        console.log("components.toolbar initialisation");

        return this;
    }

    return {
        loader: loader,
        menu: menu(),
        toolbar: toolbar
    }
}();

$(function () {

    components
        .loader()
        .menu()
        .toolbar();

    components
        .menu
            .open();

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

所以我想我的问题是,我该如何使用;嵌套、显示模块并链接在一起(如果可能的话)?

var components = (function () {

var loader = function () {
    console.log("components.loader initialisation");

    return this;
};

var menu = function () {

    var menu = function () {
        console.log("components.menu initialisation");
  
        return this;
    };
 

    menu.open = function () {
        console.log("components.menu.open");

        return this;
    };

    menu.close = function () {
        console.log("components.menu.close");

        return this;
    };

    return menu;
};

var toolbar = function () {
    console.log("components.toolbar initialisation");
 
    return this;
};

return {
    loader: loader,
    menu: menu(),
    toolbar: toolbar
};
})();

$(function () {
components
 .loader()
 .menu()
 .toolbar();

components
 .menu
  .open();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>