Глобальный модуль или глобальная переменная Javascript

Я не мог найти лучшего заголовка вопроса, извините.

Мой вопрос в he.js по https://github.com/mathiasbynens/he/blob/master/he.js, они используют следующий код:

/*! https://mths.be/he v0.5.0 by @mathias | MIT license */
;(function(root) {

    //...omitted

    var he = {
        'version': '0.5.0',
        'encode': encode,
        'decode': decode,
        'escape': escape,
        'unescape': decode
    };

    // Some AMD build optimizers, like r.js, check for specific condition patterns
    // like the following:
    if (
        typeof define == 'function' &&
        typeof define.amd == 'object' &&
        define.amd
    ) {
        define(function() {
            return he;
        });
    }   else if (freeExports && !freeExports.nodeType) {
        if (freeModule) { // in Node.js or RingoJS v0.8.0+
            freeModule.exports = he;
        } else { // in Narwhal or RingoJS v0.7.0-
            for (var key in he) {
                has(he, key) && (freeExports[key] = he[key]);
            }
        }
    } else { // in Rhino or a web browser
        root.he = he;
    }

}(this));

И если вы импортируете это на свою страницу как

<script src="he.js"></script>

Вы сможете вызвать методы на своей странице как he.encode(...).

Мой вопрос в том, как именно он устанавливает переменную he?

Я имею в виду, я вижу

    } else { // in Rhino or a web browser
        root.he = he;
    }
}(this));

Но при вызове }(this));, что именно есть this?

Ответ 1

Пусть упрощается:

;(function(root) {
    ...
}(this));

Итак, у нас есть функция, которая принимает аргумент, называемый root. Эта функция немедленно вызывается (http://benalman.com/news/2010/11/immediately-invoked-function-expression/), и мы передаем ей значение this.

В этом контексте this - ваш глобальный объект. Если вы используете браузер, ваш глобальный объект будет window.

Итак, если вы действительно используете браузер:

 root.he = he;

на самом деле то же самое, что:

window.he = he;

И обратите внимание, что нам необязательно использовать браузер, благодаря платформам вроде Node теперь существуют другие контексты, где глобальный объект this - это нечто иное, чем window. Вот почему другой не указывает window явно и проходит через это конкретное упражнение.