Объекты в JavaScript и создание JS-компонента. Часть 1

Автор оригинала: Nick Salloum
  • Перевод
  • Tutorial
Эта статья — первая часть туториала об ООП в JavaScript и о создании простого JS-компонента.

Об объектах и JavaScript


Думайте об объекте, как о совокупности каких-то вещей. Например, представьте, что у вас есть велосипед. Этот велосипед является объектом, и он имеет совокупность каких-то признаков / частей / etc, называющихся свойствами объекта. Примером такого свойства может служить модель велосипеда, год его производства, его детали. Детали также могут иметь собственный набор свойств.

JavaScript является объекто-ориентированным языком. Поэтому всё в JavaScript является объектом и имеет свой набор свойств, к которым мы можем получить доступ. Более формальное объяснение с MDN:
JavaScript основан на простой объектно-ориентированной парадигме. Объект является коллекцией свойств, а свойство — это ассоциация между именем и значением. Значение свойства может быть функцией, и в таком случае функция будет называться методом. В дополнение к стандартным объектам, уже определённым в браузере, вы можете создавать собственные объекты.

Создание собственных объектов является весьма полезной возможностью. В JavaScript мы можем получить доступ к свойствам объекта через dot notation. Но прежде чем разбираться с доступом к свойствам, давайте разберёмся с созданием и инициализацией объектов.

Создание объекта


Наверняка вы уже создавали или использовали объекты, сами того не зная, так как всё в JavaScript является объектом. Небольшая заметка с MDN:
Все примитивные типы, кроме null и undefined рассматриваются в качестве объектов. Им могут быть присвоены какие-то свойства, и они имеют все характеристики объектов.

В JavaScript существует огромное количество стандартных объектов, однако в этой статье я не буду их рассматривать. С этого момента и на протяжении всей статьи мы будем создавать очень простой JavaScript-компонент под названием «SimpleAlert». Ввиду этого давайте создадим наш собственный объект.

var simpleAlert = new Object();

// От переводчика: на самом деле, объект можно создать ещё проще.
var simpleAlert = {};

Вот и всё! Просто, не так ли? Однако, всё это не имеет смысла до тех пор, пока мы не добавим объекту какие-либо свойства. Мы можем сделать это, используя dot notation:

// создание нового объекта
var simpleAlert = new Object();

// добавление некоторых свойств
simpleAlert.sa_default = "Hello World!";
simpleAlert.sa_error = "Error...";
simpleAlert.sa_success = "Success!";

// вывод объекта в консоли
console.log(simpleAlert);

В консоли видно, что наш объект имеет 3 свойства. Поскольку мы задали эти свойства выше, мы можем получить доступ к ним в любом месте нашего скрипта. Например, если бы мы захотели послать в консоль пользователя уведомление об ошибке, мы могли бы сделать следующее:

// вывод сообщения об ошибке
alert(simpleAlert.sa_error);

Это всего лишь один из способов создания объекта и доступа к его свойствам.

Создание объекта с инициализаторами


Другой способ создания объекта — с помощью так называемых object initializer, инициализаторов объекта. Определение на MDN:
… вы можете создавать объекты с помощью инициализатора объекта. Использование инициализатора иногда называют созданием объекта с помощью literal notation. Название object initializer также соответствует терминологии, используемой в C++.

Создание нашего «SimpleAlert» таким способом будет весьма простым:

// создание нового объекта
var simpleAlert = {
  sa_default    : "Hello World!",
  sa_error      : "Error...",
  sa_success    : "Success!"
}

// вывод объекта в консоль
console.log(simpleAlert);

Свойства объекта также могут быть функциями. Например:

// создание нового объекта
var simpleAlert = {
  sa_default    : "Hello World!",
  sa_error      : "Error...",
  sa_success    : "Success!",
  sa_fallback   : function(){
    console.log("Fallback");
  }
}

// запуск fallback'a
simpleAlert.sa_fallback();

Код выше выведет в консоль строку «Fallback». Как уже упоминалось выше, когда свойство объекта является функцией, оно также может называться методом.

Использование конструктора


Другой способ создания объекта в JavaScript — использование функции-конструктора. И снова цитата с MDN:
Определите объект, написав конструктор. Хорошей практикой считается именование функции с большой буквы. Создайте экземпляр объекта, используюя ключевое слово `new`.

Вы можете прочитать больше об этом способе здесь. Создание нашего объекта с помощью конструктора:

// конструктор
function SimpleAlert( sa_default, sa_error, sa_success ) {
  this.sa_default = sa_default;
  this.sa_error = sa_error;
  this.sa_success = sa_success;
}

// создание нового объекта
var my_alert = new SimpleAlert( "Hello World!", "Error...", "Success!" );

Если мы выведем объект в консоли, то мы получим тот же результат, что и в предыдущих случаях.

console.log(my_alert); // выведет объект
console.log(my_alert.sa_error); // выведет "Error..."

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

Ещё подробнее об объектах


На самом деле, об объектах можно рассказать гораздо больше, чем я рассказал выше. Однако методы, упомянутые мной, весьма полезны, и в дальнейшем мы будем их использовать их для создания нашего компонента. Я настойчиво рекомендую прочитать материал с MDN Working with objects для того чтобы полностью разобраться с объектами. Также стоит взглянуть на документацию по объектам, чтобы иметь представление о том, какие методы и свойства для работы с ними существуют.

Создаём части нашего компонента


Мы собираемся создать компонент под названием «SimpleAlert», который выводит сообщение на экран пользователя, когда тот нажимает на кнопку. От того, какая кнопка будет нажата, зависит сообщение, которое будет выведено. Разметка для кнопок:

<div id="component">
  <button id="default">Show Default Message</button>
  <button id="success">Show Success Message</button>
  <button id="error">Show Error Message</button>
</div>

Что касается самого компонента — его код мы обернем в анонимную функцию и сделаем её доступной в глобальной области видимости. Для начала это будет выглядеть как-то так:

;(function( window ) {

  'use strict';
  
})( window );

Несколько замечаний по поводу кода:

  • Я использую strict mode. Вы можете прочитать о нём здесь.
  • Мы передаём window в нашу анонимную функцию, благодаря чему мы впоследствии сможем добавить SimpleAlert в глобальную область видимости.


Давайте напишем немного кода нашего компонента. Для начала нам нужно создать функцию SimpleAlert. Также нам нужно её в глобальную область видимости.

;(function( window ) {

  'use strict';

  /**
   * SimpleAlert function
   */
  function SimpleAlert( message ) {
    this.message = message;
  }
  
  // большинство кода будет здесь...
  
  /**
   * Добавление SimpleAlert в глобальную область видимости
   */
  window.SimpleAlert = SimpleAlert;
  
})( window );

Если мы создадим экземпляр объекта SimpleAlert, то пока что ничего не произойдет.

(function() {
  /**
   * Отобразить стандартное уведомление
   */
  var default_btn = document.getElementById( "default" );
  default_btn.addEventListener( "click", function() {
    var default_alert = new SimpleAlert("Hello World!");
  } );

})();

Прежде чем продолжить, вам следует ознакомиться с Object.prototype. MDN:
Все объекты в JavaScript являются потомками Object; все объекты наследуют свойства и методы от Object.prototype, хотя они могут быть переопределены. Исключение — объект с null-прототипом, например Object.create(null)).

Подробнее. Мы будем использовать этот подход в создании нашего компонента. Давайте добавим функцию init, и вызовем её сразу после создания объекта. Эта функция будет отправлять в консоль сообщение.

;(function( window ) {

  'use strict';

  /**
   * SimpleAlert function
   */
  function SimpleAlert( message ) {
    this.message = message;
    this._init();
  }

  /**
   * Initialise the message
   */
  SimpleAlert.prototype._init = function() {
    console.log(this.message);
  }

  /**
   * Add SimpleAlert to global namespace
   */
  window.SimpleAlert = SimpleAlert;

})( window );

Теперь созданный экземпляр объекта будет выводить в консоль сообщение «Hello, world!». Это прогресс! Теперь давайте сделаем так, чтобы сообщение выводилось на экран пользователя, а не в консоль.

;(function( window ) {

  'use strict';

  /**
   * SimpleAlert function
   */
  function SimpleAlert( message ) {
    this.message = message;
    this._init();
  }

  /**
   * Initialise the message
   */
  SimpleAlert.prototype._init = function() {
    this.component = document.getElementById("component");
    this.box = document.createElement("div");
    this.box.className = "simple-alert";
    this.box.innerHTML = this.message;
    this.component.appendChild( this.box );
  }

  /**
   * Add SimpleAlert to global namespace
   */
  window.SimpleAlert = SimpleAlert;

})( window );

Давайте по пунктам рассмотрим работу нашего кода.

  1. Мы создаём переменную message внутри конструктора и делаем её доступной внутри анонимной фунции с помощью this.message = message.
  2. Далее мы вызываем нашу функцию _init через this._init(). Каждый раз когда мы создаем новый экземпляр объекта, эти два шага автоматически выполняются.
  3. Внутри _init() мы объявляем нужные переменные с помощью ключевого слова this. Затем получаем доступ к элементу #component, и в него помещаем div, содержащий в себе сообщение.


Весьма аккуратно, правда?

Весь код


Ниже представлен весь написанный код, включая немного CSS для более приятного внешнего вида. Для начала разметка:

<div id="component">
  <button id="default">Show Default Message</button>
  <button id="success">Show Success Message</button>
  <button id="error">Show Error Message</button>
</div>

Такая же, какая была выше. Теперь немного CSS:

.simple-alert {
  padding: 20px;
  border: solid 1px #ebebeb;
}

Отредактируйте его так, как вам захочется! И, наконец, JS-код. В него я также добавил обработчики событий, чтобы при нажатии на кнопку сообщение корректно отображалось.
// COMPONENT
//
// The building blocks for our SimpleAlert component.
////////////////////////////////////////////////////////////
;(function( window ) {

  'use strict';

  /**
   * SimpleAlert function
   */
  function SimpleAlert( message ) {
    this.message = message;
    this._init();
  }

  /**
   * Инициализация компонента
   */
  SimpleAlert.prototype._init = function() {
    this.component = document.getElementById("component");
    this.box = document.createElement("div");
    this.box.className = "simple-alert";
    this.box.innerHTML = this.message;
    this.component.appendChild( this.box );
    this._initUIActions;
  }

  SimpleAlert.prototype._initUIActions = function() {

  }

  /**
   * Добавляем SimpleAlert в глобальную область видимости
   */
  window.SimpleAlert = SimpleAlert;

})( window );


// EVENTS
//
// Код для создания новых экземпляров объекта
// в зависимости от нажатой кнопки.
////////////////////////////////////////////////////////////
;(function() {
  
  /**
   * Show default
   */
  var default_btn = document.getElementById( "default" );
  default_btn.addEventListener( "click", function() {
    var default_alert = new SimpleAlert("Hello World!");
  } );

  /**
   * Show success
   */
  var default_btn = document.getElementById( "success" );
  default_btn.addEventListener( "click", function() {
    var default_alert = new SimpleAlert("Success!!");
  } );

  /**
   * Show error
   */
  var default_btn = document.getElementById( "error" );
  default_btn.addEventListener( "click", function() {
    var default_alert = new SimpleAlert("Error...");
  } );

})();


Подведём итог


В этой статье мы рассмотрели создание простого JavaScript-компонента с помощью объектов. Этот компонент прост, но его код даёт нам фундаментальные знания для создания многократно используемых и расширяемых компонентов. На досуге подумайте, как можно реализовать кнопку «закрыть оповещение» (подсказка — нажатие кнопки должно запустить метод hide()).

В следующей части мы немного усовершенствуем SimpleAlert, а также узнаем, как устанавливать параметры по умолчанию и как передавать собственные наборы параметров. Вот когда вся красота программирования будет видна в действии!

Я надеюсь, что вам понравилась эта статья. Ждите вторую часть. Спасибо за чтение!
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 3

    +4
    Какой-то вредный код. Во-первых внутри функция-инициалиазатор _init выполняет несколько функций сразу:
    1. Инициализирует внутреннее состояние.
    2. Выполняет вставку элемента в dom.

    Поэтому лучше разбить: отдельно _init, отдельно вставка в dom,
    Зачем вообще нужен метод _init? Если у нас уже есть конструктор? Зачем пихать в this message? message короткоживущий объект внутри верстки, зачем он нам вообще нужен?

    Зачем вообще засорять window? Есть уже нормальные модульные системы, которые работают, забудьте window, не путайте новичков. Используйте CommonJS или лучше UMD, или SystemJS.

    Таким образом:
    ;(function( window ) {
    
      'use strict';
    
      /**
       * SimpleAlert function
       */
      function SimpleAlert( ) {
        this.component = document.getElementById("component");
        this.box = document.createElement("div");
        this.box.className = "simple-alert";
      }
    
    SimpleAlert.prototype.render = function (msg) {
        msg = msg || this.box.innerHTML || '';
        this.box.innerHTML = msg;
        this.component.appendChild( this.box );
    };
    
      /**
       * Добавляем SimpleAlert в глобальную область видимости
       */
      window.SimpleAlert = SimpleAlert;
    
    })( window );
    
    
    ;(function() {
      var default_btn = document.getElementById( "default" );
      default_btn.addEventListener( "click", function() {
        var default_alert = new SimpleAlert();
       default_alert.render("Hello World!");
      } );
    })();
    


    З.Ы. Код не проверил, поэтому возможны ошибки. Просто показать направление мысли.
      0
      Скажите, что значит ";" перед анонимной функцией? Еще встречал "+" в некоторых плагинах. Подозреваю, что эти символы имеют схожий смысл в данной ситуации.
        0
        Смысл; это избежать проблем при минификации файлов, если кто-то из соседнего файла забыл поставить; а умный минификатор пропустил предупреждение мимо ушей.
        Пример:
        Дано:
        var a = 10
        (function(){})() 
        
        

        После минификации:
        var a = 10(function(){})() 
        


        А если мы поставим; то будет так:
        var a = 10;(function(){})()
        


        Вы говорите о другом случае об IIFE, подробнее о способах их написания в п.6 Javascript F.A.Q.:
        habrahabr.ru/post/124327/

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое