What is the purpose of this JavaScript trick?



  • Alright, so you have a page that you want to run JavaScript on startup. Typically, I would do this:

    <script language="JavaScript">
    function Startup ()
    {
      ...
    }
    </script>
    <body onload="JavaScript:window.Startup();">
    

    But I've seen more and more webpages that do something like this instead:

    <script language="JavaScript">
    (function(){...})();
    </script>
    <body>
    

    So...is there a benefit to doing this besides making it harder for somebody to force re-execution of the function from the URL bar?


  • Considered Harmful


  • :belt_onion:

    @Zenith said in What is the purpose of this JavaScript trick?:

    Alright, so you have a page that you want to run JavaScript on startup. Typically, I would do this:

    <script language="JavaScript">
    function Startup ()
    {
      ...
    }
    </script>
    <body onload="JavaScript:window.Startup();">
    

    But I've seen more and more webpages that do something like this instead:

    <script language="JavaScript">
    (function(){...})();
    </script>
    <body>
    

    So...is there a benefit to doing this besides making it harder for somebody to force re-execution of the function from the URL bar?

    I think the most obvious benefit is that the code executes itself, rather than not obviously doing that. Your onload tag is a level of action-at-a-distance (minor, but still)



  • Another difference is that the function expression would be evaluated/executed as soon as the </script> tag is parsed, whereas the other way it has to wait until the document's onload handler fires.


  • 🚽 Regular

    @Zenith With an IIFE (as per error's post) you're not "poluting" the window object with a Startup member.


    <body onload="JavaScript:window.Startup();">

    Inline attributes with JavaScript ? What year is this?

    <script>
        window.addEventListener('DOMContentLoaded', Startup, false):
    </script>
    <body>
    

    Or even

    <script>
        window.addEventListener('DOMContentLoaded', function() {
            // Do shit
        }, false):
    </script>
    <body>
    

    Congrats on avoid jQuery, I guess?


  • 🚽 Regular

    Confession time (yes, I know we have a thread for that:

    let handlerName = someuuid + "-handler";
    
    let handler = ({[handlerName]:
        function (args){
            // ...
        }
    })[handlerName];
    
    // handler.name is now magically '<someuuid>-handler'. Yes, even if it starts with a digit.
    // The alternative would have been to use Object.defineProperty(), which frankly would have been clearer

  • Discourse touched me in a no-no place

    @Zecc said in What is the purpose of this JavaScript trick?:

    @Zenith With an IIFE (as per error's post) you're not "poluting" the window object with a Startup member.


    <body onload="JavaScript:window.Startup();">

    Inline attributes with JavaScript ? What year is this?

    Look who created the topic. I guess we're lucky no <div>s were involved 🎺



  • @Watson I thought this would come up but changing the question was :kneeling_warthog:. When I had inline JavaScript, it was literally inlined and not wrapped in a function. All of that went away with better server side code though.

    Maybe "polluting" the window object is a bigger deal in SPAs where 40MB of framework comes along with every request. I started putting my library into a fake namespace object but prior to that had very minimal scripting per page.



  • @Zenith It makes you spend a bunch of time trying to figure out why folks do A instead of B?

    FWIW: I looked at one of my past projects and the HTML file doesn't have any inline JavaScript. It loads a few .js files, the last of which has a window.addEventListener("load", initPage); at the end. 🤷🏻♂



  • @loopback0 said in What is the purpose of this JavaScript trick?:

    Look who created the topic. I guess we're lucky no <div>s were involved

    But I can't unsee the <script language="JavaScript>. The language attribute has been deprecated for decades now, hasn't it? Even in HTML 4, you were supposed to use type instead.

    Using load instead of DOMContentLoaded is the worse sin, though, because it actually affects the user experience.


  • :belt_onion:

    @dfdub said in What is the purpose of this JavaScript trick?:

    Using load instead of DOMContentLoaded is the worse sin, though, because it actually affects the user experience.

    In a huge, huge, deleterious way. To such an extent that I would call it wrong without compelling evidence that there's code in there that must run before the DOM is available and it has negligible performance impact.



  • @dfdub said in What is the purpose of this JavaScript trick?:

    But I can't unsee the <script language="JavaScript>. The language attribute has been deprecated for decades now, hasn't it? Even in HTML 4, you were supposed to use type instead.

    Considering the only browser to support an alternative langauge was Internet Explorer, why use either of them? Same goes for the style tag really.

    @heterodox said in What is the purpose of this JavaScript trick?:

    @dfdub said in What is the purpose of this JavaScript trick?:

    Using load instead of DOMContentLoaded is the worse sin, though, because it actually affects the user experience.

    In a huge, huge, deleterious way. To such an extent that I would call it wrong without compelling evidence that there's code in there that must run before the DOM is available and it has negligible performance impact.

    Mozilla says the DOMcontentloaded event happens before the load event.

    "The DOMContentLoaded event is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the load event can be used to detect a fully-loaded page)."

    So what did you really mean there? Should I wait for the document to actually finish loading or not?

    Also keep in mind I don't use JavaScript to draw my entire page and hook up every event. What I used Startup() for was to load compatibility functions/overrides, make parts of the window unselectable, and make everything visible (I fucking hate pages that jerk all over while loading so I don't show everything until it's loaded). I also had a Destroy() in onunload to clean up stuff.

    @Zecc said in What is the purpose of this JavaScript trick?:

    Inline attributes with JavaScript ? What year is this?

    The year where my pages are fast to load, are fast to execute, don't stutter on scrolling, and don't make my phone heat up.

    @Parody said in What is the purpose of this JavaScript trick?:

    It makes you spend a bunch of time trying to figure out why folks do A instead of B?

    My guess was that the anonymity was the desirable aspect. With so much logic shoved into client side script these days, security by obscurity has been the predominant model (see also minification misuse). I just wanted to see if there was an actual benefit that I was overlooking. I guess the scoping argument satisfies that but I always viewed inline scripting in the same light as document.write() (a bad shortcut that slowed down DOM operations).



  • @Zenith said in What is the purpose of this JavaScript trick?:

    The year where my pages are fast to load, are fast to execute, don't stutter on scrolling, and don't make my phone heat up.

    You can say that again. Remember when you could open a web page in a background window/tab and it would be fully loaded when you switched to it? Too often nowadays I switch to a tab and see the site for just long enough to know it was there before everything disappears and reloads. Then there's the myriad times a page loads everything except what you actually wanted to see and then sits there, giving you no idea if it's done, it failed, or it's loading something in the background without telling you. In all three cases the browser's loading indicator shows that it's done. :rolleyes:



  • @Zenith said in What is the purpose of this JavaScript trick?:

    Considering the only browser to support an alternative langauge was Internet Explorer, why use either of them? Same goes for the style tag really.

    I think the HTML5 spec allows you to omit the type attribute for both. But if you're specifying the language explicitly anyway, you might as well do it the standard way.

    Fun fact: The HTML 4 spec uses Tcl as an example of an alternative scripting language inside HTML for some reason.

    Mozilla says the DOMcontentloaded event happens before the load event.
    "The DOMContentLoaded event is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the load event can be used to detect a fully-loaded page)."

    I think @heterodox missed the part where you executed your code as a load handler and thought you ran it immediately. In any case, DOMContentLoaded is the event you should use 99.9% of the time, especially if you want your modifications to be invisible to the user.


  • Discourse touched me in a no-no place

    @dfdub said in What is the purpose of this JavaScript trick?:

    Fun fact: The HTML 4 spec uses Tcl as an example of an alternative scripting language inside HTML for some reason.

    There were early versions of the in-browser scripting work that used Tcl. That Javascript won out was pure random.



  • I considered tagging you to ask you, but apparently that was unnecessary. Mentioning Tcl is sufficient to summon you.


  • Discourse touched me in a no-no place

    @dfdub Usually just writing anything is enough. I catch up most active threads (outside the 🚎). Occasionally I miss stuff, but it's not intentional. 😉


  • BINNED

    @Zenith said in What is the purpose of this JavaScript trick?:

    I also had a Destroy() in onunload to clean up stuff.

    Um, what?
    I have no JS/HTML experience, so I might be completely missing something here, but that sounds like "sweeping the floor when the building is about to be demolished."



  • Scoping is the main reason to do this, yeah. There's also a related idiom to 'rename' globals, mostly used with jQuery:

    function($) {
     ... // bunch of stuff using $
    }(jQuery);

    Re load handlers - I, too, don't see the problem with <body onload="...">. Being able to attach handlers in Javascript is nice (particularly now you don't need to worry about addEventListener vs attachEvent, if you're not coding for dinosaur-era IE) but if you know the handler at the time you're serving (or writing) the page, what's wrong with a static declaration?


  • 🚽 Regular

    @dkf said in What is the purpose of this JavaScript trick?:

    There were early versions of the in-browser scripting work that used Tcl. That Javascript won out was pure random.

    I had no idea.



  • @dfdub said in What is the purpose of this JavaScript trick?:

    Fun fact: The HTML 4 spec uses Tcl as an example of an alternative scripting language inside HTML for some reason.



  • @topspin said in What is the purpose of this JavaScript trick?:

    @Zenith said in What is the purpose of this JavaScript trick?:

    I also had a Destroy() in onunload to clean up stuff.

    Um, what?
    I have no JS/HTML experience, so I might be completely missing something here, but that sounds like "sweeping the floor when the building is about to be demolished."

    You'll see references to "destroy" in parts of the Win32 API where they're allocating and deallocating resources (like DestroyIcon() and WM_DESTROY). I also learned to program in C/C++ where it was common to define a constructor and destructor whether or not they did anything. In top of that, I like symmetry, so having two seven letter functions to bookend stuff like this just looks right to me in many contexts/languages.



  • @sloosecannon said in What is the purpose of this JavaScript trick?:

    Your onload tag is a level of action-at-a-distance

    :rolleyes: contrariwise, for once the operation is set on the affected thing, which is the opposite of action at a distance; and that's precisely why we Can't Have That on the web.

    Web programming is all based on action-at-a distance, and not doing that is considered the canonical no-no. You have the HTML "pretend I was a dumb static document without any formatting or dynamic behavior, no siree!" over here, then you have the CSS "pretend we can apply formatting to a document as an after-thought" over there, and finally of course you have the javascript "pretend this central part that brings the app to life and makes it actually do anything useful is purely accessory" in a third place. And of course, all of these pieces are tied together through assumptions and intricate inter-dependencies so that if you change anything in one place you'll have to modify the related parts of the other two.


    inb4 the World Wide Web Inquisition tells me how wrong and impure I am. I've heard your arguments , they all sound very beautiful and righteous, and seem to fall apart as soon as they get into any contact with reality.



  • @topspin said in What is the purpose of this JavaScript trick?:

    @Zenith said in What is the purpose of this JavaScript trick?:

    I also had a Destroy() in onunload to clean up stuff.

    Um, what?
    I have no JS/HTML experience, so I might be completely missing something here, but that sounds like "sweeping the floor when the building is about to be demolished."

    I learned to program in C/C++. It was common to define a constructor and destructor whether or not they did anything. Win32 also has several references to "destroy" in its allocating functions. Plus, I like symmetry, so it makes sense to me to have Startup() and Destroy() to bookend processes and both having seven letters is a bonus.


Log in to reply