Namespaces в JavaScript. Ставим точку в вопросе

от автора

Развитие языка javascript переносит выполнение кодов на распределенную сеть пользователей и снимает нагрузку с сервера. Это разумный подход. Введение в js ключевых слов class, extends и static дало возможность легко моделировать классами и объектами предметную область проекта. Это замечательно. Следующий вопрос, который необходимо рассмотреть при возрастании сложности js-проекта — это пространство имен. Именно оно позволяет избежать конфликтов с ворохом разнородных js-скриптов. Как показывает практика с этим вопросом почему-то возникли большие сложности. Смотрим ссылки ниже:

https://support.qbpro.ru/index.php?title=Базовые_Namespace_паттерны_JavaScript

https://habr.com/ru/post/527610/

https://drbrain.ru/articles/js-namespaces/

https://stackoverflow.com/questions/881515/how-do-i-declare-a-namespace-in-javascript

Плохо, только запутали все и многие решения сложны.

Есть еще и стандартная схема с использованием import, export модулей:

https://learn.javascript.ru/modules-intro

https://habr.com/ru/company/domclick/blog/532084/

За модулями конечно будущее, но с ними возникает пара вопросов — это локальное их использование без сервера (CORS policy), а главное поддержка их браузерами все еще не завершена (многопоточно web-workers не обработают модули, старые браузеры тоже не понимают):

https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Modules

Многопоточный веб-worker по-своему захватывает скрипты:

https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts

Ладно, учтем комментарии и выберем для сравнения схему (паттерн) пространства имен, такую что многопоточные workers будут довольны и интернет заработает. Для улучшенного понимания остановимся на варианте где количество стрелочек, скобочек и прочих засоряющих человеческое восприятие закорючек минимально.

/**   * @namespace namespaceOne  */ const namespaceOne = new function(){         class First {         //статическое свойство         static className = "First";         constructor() {             console.log("class First consructed");         }          print() {             console.log("First print");         }          //статическая функция         static printStatic() {             console.log(First.className + " static print ");         }     }      //наследование     class Second extends First {         constructor() {             super();             Second.className = "Second";             console.log("class Second consructed");         }         //полиморфизм         print() {             console.log(Second.className + " print");         }     }      class Third {         className;         encapsulation;         constructor() {             this.className = "Third";             this.encapsulation = new Second(); //инкапсуляция             console.log("class Third consructed");         }         print() {             console.log("Third print");         }     }     console.log("namespaceOne code done");     //экспорт пространства имен     return {First: First, Second: Second, Third: Third}; };  /**   * @namespace namespaceTwo  */ const namespaceTwo = new function(){         class First {                 constructor() {             console.log("other class First consructed");         }          print() {             console.log("other First print");         }            }     //экспорт пространства имен     return {First: First}; };  /**   * @namespace namespaceThree  */ const namespaceThree = new function(){     //импорт пространства имен     namespaceOne.First.printStatic();     let second = new namespaceOne.Second();     second.print();      let ThirdClass = namespaceOne.Third;     let third = new ThirdClass();     third.print();          let first1 = new namespaceOne.First();     let first2 = new namespaceTwo.First();     first1.print();     first2.print(); };

Теперь можно смело добавлять ваш код в любой проект. С большой вероятностью конфликтов не возникнет. Минус такого решения: надо добавлять комментарии, что вот такие конструкции: const namespaceYou = new function(){...} - являются namespace, а не чудной функцией.

Есть и более простой вариант не засорять общее пространство кодом (некоторая экологичность так сказать) — это просто взять ваш код в фигурные скобки { } и не злоупотреблять модификаторами var и function:

{ //namespace1     class Simple {         constructor() {             console.log("Simple created");         }         print() {             console.log("Simple called");         }     }      let simple = new Simple();      //экспорт      var namespace1 = {simpleObject: simple, SimpleClass: Simple}; }  {//namespace2     namespace1.simpleObject.print();     let simple = new namespace1.SimpleClass(); }

Красота.

Когда нибудь веб-workers начнут работать с модулями, а CORS policy разрешит писать вам локальные модульные js-приложения и все это уйдёт в историю. Когда-нибудь …


ссылка на оригинал статьи https://habr.com/ru/articles/583130/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *