Инкапсуляция в JavaScript
Давным-давно я видел, как кто-то инкапсулировал весь свой блок JavaScript с кодом вроде кода ниже:
(function() {
// ...
})(this);
Вопросы:
- Правильно ли указан код?
- Какая польза от инкапсуляции всего блока JavaScript, как указано выше?
Ответы
Ответ 1
Да, это правильно. Он называл самоисключение анонимного выражения функции.
Переменные JavaScript имеют либо область действия, либо глобальную область. Объем блока не ограничен. Включение вашего кода в функцию самозапуска, подобную той, что приведена в вашем примере, создает временную локальную область для одноразового, немедленного запуска кода без загрязнения глобального пространства имен.
Рассмотрим следующее:
<html>
<body>
...
<script>
(function() {
var x = '';
function myFunction () {
alert('Hello: ' + x);
}
x = 'Bob';
myFunction();
alert(typeof x); // string
alert(typeof myFunction); // function
})();
alert(typeof x); // undefined
alert(typeof myFunction); // undefined
</script>
<script src="other-javascript.js"></script>
</body>
</html>
Все, что вы заявляете в этой функции самозапуска, хранится в отдельной области. Переменная x
и функция myFunction()
недоступны нигде. Например, код в other-javascript.js
не увидит их, и было бы свободно объявлять другую функцию myFunction()
без конфликтов.
Ответ 2
В дополнение к ответу @Daniel передача this
в функцию - это общий шаблон для ссылки на глобальный объект, например:
(function(window){
})(this);
В сценарии браузера глобальный объект имеет свойство с именем window
, которое относится к самому глобальному объекту, в других средах нет свойства window
.
Кроме того, еще одна вещь, которую можно сделать, - указать аргумент с именем undefined
, поскольку свойство undefined
не описано в ECMAScript 3rd. Standard Edition (нет гарантии, что существуют или нет), а в некоторых реализациях свойство изменено, например:
(function(window, undefined){
})(this);
В приведенном выше примере у нас есть два локальных идентификатора (которые немного быстрее разрешены), window
и undefined
, передается только первый (this
, который всегда ссылается на глобальный объект в Глобальный код (код, который находится вне любой функции)), а второй будет содержать примитивное значение undefined
, потому что мы не проходим мимо любое значение для него.
Этот шаблон используется некоторыми библиотеками, такими как jQuery.
Ответ 3
Для справки, ECMA TC39 предложил частный синтаксис. Согласно предложению, для того, чтобы сделать поле класса javascript закрытым, необходимо добавить к нему хеш '#'. Это делается для обеспечения некоторой инкапсуляции во время выполнения.
Пример:
class B {
#hidden = 0;
m() {
return this.#hidden;
}
}
Chrome поддерживает это начиная с Chrome v74. Если этот частный синтаксис станет стандартом, мы сможем извлечь выгоду из инкапсуляции во время выполнения в javascript и, предположительно, в typcript, поскольку его преобразование будет обновлено таким образом.