БлогNot. Как сделать собственную Javascript-библиотеку

Как сделать собственную Javascript-библиотеку

Если Вы заглядывали в исходник любого из ныне популярных Javascript-фреймворков, Вы наверняка видели там подобный код. В этой заметке показан шаблон для написания собственной библиотеки на Javascript, а также пример вызова её функций. Я не стал изобретать велосипед, ограничившись типовым подходом. На самом деле, можно сделать и просто класс на Javascript, только не станет ли это медленней при увеличении количества свойств и методов класса? Да и разделение данных класса на приватные и публичные Javascript пока нормально не поддерживает, имея как раз альтернативные механизмы для этого в виде "обёрток".

Как бы то ни было, здесь приведён ставший уже классическим подход с анонимной функцией-обёрткой и инкапсулированным в неё объектом. Предполагается, что файлы примера будут размещены в одной папке под указанными именами и иметь кодировку Юникода UTF-8. В листингах есть комментарии, помогающие понять основные действия.

Шаг 1. Делаем шаблон

Стараемся сделать код будущей библиотеки защищённым от "внешних воздействий" и конфликтов имён, так, чтобы он был доступен через единое "внешнее имя" объекта библиотеки.

Здесь и далее предполагается, что оба файла сохраняются в одной папке.

файл lib.js
(function(window) { //Анонимная обёртка для всего
 'use strict'; //Строгое соблюдение синтаксиса
 function myLibrary() { //Обёртка для нашего кода
  var _myLibraryObject = {};

  //здесь будут функции библиотеки

  return _myLibraryObject;
 }

 // Чтобы библиотека была глобально доступна, 
 //сохраним объект в контексте глобального объекта window
 if( typeof (window.myWindowGlobalLibraryName) === 'undefined') {
  window.myWindowGlobalLibraryName = myLibrary();
 }
})(window); //Обёртка вызывает себя, передавая себе объект window
файл lib_test.html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Собственная JS-библиотека</title>
</head>
<body>

<script src="lib.js"></script>
<script>
 console.log(myWindowGlobalLibraryName);
</script>
<noscript>Please, switch on Javascript</noscript>

</body></html>
Шаг 2. Создаем функции для своей библиотеки

Создаём и прописываем функции, которые будут выполнять нужные действия над своими аргументами и возвращать результаты.

файл lib.js
(function(window) { //Анонимная обёртка для всего
 'use strict'; //Строгое соблюдение синтаксиса
 function myLibrary() { //Обёртка для нашего кода
  var _myLibraryObject = {};

  //Просто создаём свойства для своего объекта
  _myLibraryObject.myCustomLog = function (thingToLog) {
   console.log ("My-Custom-Log > Тип переменной : " + typeof(thingToLog));
   console.log ("My-Custom-Log > Является ли числом : " + !isNaN(thingToLog));
   console.log ("My-Custom-Log > Длина : " + (thingToLog).length);
   return console.log (thingToLog);
  };

  return _myLibraryObject;
 }

 // Чтобы библиотека была глобально доступна, 
 // сохраним объект в контексте глобального объекта window
 if( typeof (window.myWindowGlobalLibraryName) === 'undefined') {
  window.myWindowGlobalLibraryName = myLibrary();
 }
})(window); //Обёртка вызывает себя, передавая себе объект window
файл lib_test.html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Собственная JS-библиотека</title>
</head>
<body>

<script src="lib.js"></script>
<script>
 myWindowGlobalLibraryName.myCustomLog(["Моя библиотека","123"]);
</script>
<noscript>Please, switch on Javascript</noscript>

</body></html>
Шаг 3. Создаём приватные или общедоступные свойства объекта библиотеки

Чтобы сохранить настройки или другие свойства, не представляющие интереса для пользователя (или просто некие промежуточные данные), мы можем объявить обычную переменную settings в области действия нашей функции, и ее нельзя будет получить за пределами оболочки.

Хотя settings не может быть получена за пределами вашей оболочки, можно создать метод, который всё-таки позволяет это (см. getSettings).

файл lib.js
(function (window) { //Анонимная обёртка для всего
 'use strict'; //Строгое соблюдение синтаксиса
 function myLibrary() { //Обёртка для нашего кода
  var _myLibraryObject = {};

  // Эта переменная будет недоступна для пользователя, 
  // она будет видна только в пределах вашей библиотеки
  var settings = {
   volume: 100,
   mute:   false
  };

  //Методы для изменения и/или получения приватных свойств: 

  _myLibraryObject.setVolume = function (volume) {
   if (isNaN(volume) || !isFinite(volume)) volume = 0;
   if (volume < 0) volume = 0;    //Проверяем корректность аргумента,
   if (volume > 100) volume = 100; //при необходимости исправляя их
   settings.volume = volume;
   return volume;
  };
    
  _myLibraryObject.setMute = function(muteStatus) {
   if (typeof(muteStatus) === 'boolean') { //Проверяем корректность аргумента
    settings.mute = muteStatus;
   }
   else { //с выводом сообщения об ошибке в консоль
    console.error("Настройка mute принимает значения только true или false");
   }
   return settings.mute;
  };

  _myLibraryObject.getVolume = function() {
   return settings.volume;
  };
    
  _myLibraryObject.getMute = function() {
   return settings.mute;
  };

  //Просто создаём свойства для своего объекта
  _myLibraryObject.myCustomLog = function (thingToLog) {
   console.log ("My-Custom-Log > Тип переменной : " + typeof(thingToLog));
   console.log ("My-Custom-Log > Является ли числом : " + !isNaN(thingToLog));
   console.log ("My-Custom-Log > Длина : " + (thingToLog).length);
   return console.log (thingToLog);
  };

  //Переменная settings будет представлена этим объектом
  _myLibraryObject.getSettings = function() {
   return settings;
  };

  return _myLibraryObject;
 } //конец myLibrary()

 // Чтобы библиотека была глобально доступна, 
 //сохраним объект в контексте глобального объекта window
 if (typeof (window.myWindowGlobalLibraryName) === 'undefined') {
  window.myWindowGlobalLibraryName = myLibrary();
 }
})(window); //Обёртка вызывает себя, передавая себе объект window
файл lib_test.html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Собственная JS-библиотека</title>
</head>
<body>

<script src="lib.js"></script>
<script>
 console.log (myWindowGlobalLibraryName.setVolume(50));
 console.log (myWindowGlobalLibraryName.setMute(true));
 console.log (myWindowGlobalLibraryName.setVolume(110)); //ошибка!
 console.log (myWindowGlobalLibraryName.getSettings());
</script>
<noscript>Please, switch on Javascript</noscript>

</body></html>
Шаг 4. Улучшаем библиотеку и добавляем интерфейс для работы с её методами

Не очень хорошо, что метод myCustomLog сам выводит информацию в консоль. Лучше, если он возвращает строку, а вызывающий скрипт решает, что с этой строкой делать.

Кроме того, пользователю нашей библиотеки может понадобиться написать интерфейсный код для работы с ней. В изменённом файле lib_test.html данные для логирования берутся из поля ввода с идентификатором myWindowGlobalLibraryNameData (наше глобальное имя библиотеки очень длинное, Ваше, возможно, будет короче, но всегда лучше соблюдать единый стиль именования объектов, относящихся к одной предметной области).

файл lib.js
(function (window) { //Анонимная обёртка для всего
 'use strict'; //Строгое соблюдение синтаксиса
 function myLibrary() { //Обёртка для нашего кода
  var _myLibraryObject = {};

  // Эта переменная будет недоступна для пользователя, 
  // она будет видна только в пределах вашей библиотеки
  var settings = {
   volume: 100,
   mute:   false
  };

  //Методы для изменения и/или получения приватных свойств: 

  _myLibraryObject.setVolume = function (volume) {
   if (isNaN(volume) || !isFinite(volume)) volume = 0;
   if (volume < 0) volume = 0;    //Проверяем корректность аргумента,
   if (volume > 100) volume = 100; //при необходимости исправляя их
   settings.volume = volume;
   return volume;
  };
    
  _myLibraryObject.setMute = function(muteStatus) {
   if (typeof(muteStatus) === 'boolean') { //Проверяем корректность аргумента
    settings.mute = muteStatus;
   }
   else { //с выводом сообщения об ошибке в консоль
    console.error("Настройка mute принимает значения только true или false");
   }
   return settings.mute;
  };

  _myLibraryObject.getVolume = function() {
   return settings.volume;
  };
    
  _myLibraryObject.getMute = function() {
   return settings.mute;
  };

  //Просто создаём свойства для своего объекта:

  _myLibraryObject.myCustomLog = function (thingToLog) {
   let s = 
    "My-Custom-Log > Тип переменной : " + typeof(thingToLog)+"\n"+
    "My-Custom-Log > Является ли числом : " + !isNaN(thingToLog)+"\n"+
    "My-Custom-Log > Длина : " + (thingToLog).length;
   return s;
  };

  //Переменная settings будет представлена этим объектом
  _myLibraryObject.getSettings = function() {
   return settings;
  };

  return _myLibraryObject;
 } //конец myLibrary()

 // Чтобы библиотека была глобально доступна, 
 //сохраним объект в контексте глобального объекта window
 if (typeof (window.myWindowGlobalLibraryName) === 'undefined') {
  window.myWindowGlobalLibraryName = myLibrary();
 }
})(window); //Обёртка вызывает себя, передавая себе объект window
файл lib_test.html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Собственная JS-библиотека</title>
</head>
<body>

<p>Введите число или строку и нажмите TAB для обновления информации:</p>
<input type="text" id="myWindowGlobalLibraryNameData" onchange="doit();">
<div id="myWindowGlobalLibraryNameResult"></div>
<script src="lib.js"></script>
<script>
function doit() {
 let val = document.getElementById('myWindowGlobalLibraryNameData').value;
 let res = myWindowGlobalLibraryName.myCustomLog (val);
 document.getElementById('myWindowGlobalLibraryNameResult').innerHTML = res;
}
</script>
<noscript>Please, switch on Javascript</noscript>

</body></html>

теги: программирование javascript

31.01.2021, 17:59; рейтинг: 202