2

I'd like to alias the window and document objects in my require modules (for both speed purposes and sanity checks).

For instance, I'd like to write:

define([`jQuery`, `window`, `document`], function($, window, document, undefined) {
    var element = document.getElementByClassName("test");
    // more code here
});

Passing in window and document is common good practice among JS modules (good explanation here: http://toddmotto.com/what-function-window-document-undefined-iife-really-means/).

How do I pass window and document in to my require modules? Is there something I can do in my require.config.paths object?

I can't seem to find any resources online that tell me how to do it.

Thanks!

user3757174
  • 483
  • 2
  • 8
  • 17

2 Answers2

2

You need to define a module that exports each of them - window, document and undefined.

So, in a window.js file, you do:

define(function(){
    // that's the actual `window` global object
    return window;
});

Then, you reference it, like you would do with any other module:

define(['jQuery', 'window'], function($, window) {
    // ...
});

Do same to cover all others you need.

However, I wouldn't recommend you to continue applying this approach. There were 2 general reasons why this approach was valuable.

  1. It's a hack for a better compression rate. If undefined is a variable in the function scope rather than a global object property, minifies can reduce it to a single letter (thus achieving a better compression rate).

    However, that's valid if you only use minification only. If you use minification + gzip to serve your production scripts (like you should!), the approach is irrelevant. Gzip uses the LZ77 algorithm that replaces repeated occurrences of data with references. So it will catch & compress all window or document or undefined or any other related occurrences and you're safe.

  2. Before ES5*, undefined was a property of the global object without write-protection. So it could be overwritten, resulting in strange and unexpected behavior.

    However, with ES5, the global properties undefined, NaN and Infinity became read-only. So with its general adoption in all modern browsers - of course with the exception of IE 9 - overwriting those values was not possible anymore.

    Plus, with ES6 we have the Proxy. If we suspense that someone is modifying a global variable, you can use a proxy to debug (track) any and every property access or set event, with a handler.get or handler.set trap. Read more about Proxies here.

Community
  • 1
  • 1
Kaloyan Kosev
  • 12,483
  • 8
  • 59
  • 90
0

It's a very nice article about IIFE. But I didn't see any point of passing document and window objects and didn't see any benefit. Those are available everywhere in your project, there is no need of passing. He took window and documents objects just for illustration.

Correct me if I am wrong. Open to correction.

Rajeev
  • 312
  • 3
  • 10
  • 1
    The first benefit is speed. If I can use a local copy of window, then when I write `if (typeof x === "undefined")`, I can check the type of `x` against the local window object's undefined property as opposed to traversing all the way up the DOM tree to get to the global window. – user3757174 Aug 21 '15 at 03:28
  • Another reason is for sanity. Going back to the `if (typeof x === "undefined")` example: because the window object is mutable, other code can change the value of the window's undefined property. If this happens, `typeof x` won't equal undefined --> it'll instead be equal to whatever the other code set it to. This can cause bugs in the code. – user3757174 Aug 21 '15 at 03:29
  • but this doesn't answer the question. – JohnnyQ Sep 06 '16 at 17:48