javascriptjquerydesign-patternsmodular-design

Using modular design pattern in Javascript with DOM selections


I have been following the Modular Design Pattern for quite some time now and find it extremely useful as it helps in the well maintenance of code & separation of blocks into modules.

Regular usage of the module structure with jQuery has led to most of my applications/code following the below structure:

(function() {
    var chat = {
        websocket: new WebSocket("ws://echo.websocket.org/"),
        that: this,
        init: function() {
            this.scrollToBottom();
            this.bindEvents();
            this.webSocketHandlers();
        },
        bindEvents: function() {
            this.toggleChat();
            this.filterPeople();
            this.compose();
        },
        elements: {
            indicator: $(".indicator"),
            statusText: $(".status-text"),
            chatHeadNames: $(".people li .name"),
            filterInput: $("#filter-input"),
            msgInput: $("#msg-input"),
            sendBtn: $(".send")
        },
        ...
        ...
        ...
        filterPeople: function() {
          var that = this;
          this.elements.chatHeadNames.each(function() {
              $(this).attr('data-search-term', $(this).text().toLowerCase());
          });
        },
        ...
        ...
        };

        chat.init();
})();

What I would like to know is whether referencing all my elements via jQuery as part of a single variable chat.elements is a good practice?

One part of me tells that it indeed is a good way to reference all your selectors at once and cache them in variables so that multiple usages of the same element can be done with the cached variables (instead of multiple DOM selections).

Another part of me tells that this might be an anti-pattern and specific elements should be selected and cached locally when required.

I have used similar structures throughout and have got mixed responses about the code, but nothing solid. Any help would be appreciated. Thanks!


Solution

  • Caching the selectors is a good thing. Hanging on to them is a good idea. It improves performance over repeatedly querying the DOM for the same thing. The code you have above looks very similar to BackboneJS and MarionetteJS code.

    I do have some warnings for you though:

    1. This pattern could cause memory leaks. Consider the case where you destory a subview, but you keep a reference to something that selected it. This is called a dangling pointer. The view won't really disappear. All bindings will remain. Events will continue to fire behind the scenes.
    2. You will eventually run into a bug where you decided to re-render part of your screen. Cleaning up all your bindings is then required and you need to remember to delete and selectors. If you don't do this you will almost certainly run into issues where you wonder why an event is indeed firing but nothing appears to happen on screen.... (this will be because its happening off screen, to the element that you tried to delete, that still exists... sorta).
    3. The current way you are querying for elements causes searches against the entire page. Take a look at https://api.jquery.com/find/. If you cache one selector and then perform searches within that selector it may gain you a little performance bump.