Javascript для новичков или немного о приватности

в 17:58, , рубрики: javascript

Для тех, кто приходит в Javascript с класс-ориентированных языков программирования, этот язык вызывает некоторые вопросы (у меня они точно возникли). У Javascript свой подход к ООП. Помимо создания объектов просто через фигурные скобки, язык предоставляет возможность использования конструкторов. И здесь начинаются интересные вещи. Если поискать в интернете, то существует два основных подхода к созданию конструкторов.

Первый: создать конструктор и в него поместить все нужные методы и свойства будущего объекта:

function Animal(name) {
  this.speed = 0;
  this.name = name;

  this.run = function(speed) {
    this.speed += speed;
    alert( this.name + ' бежит, скорость ' + this.speed );
  };

};

Второй: создать конструктор как конструктор, а необходимые методы поместить в prototype:

function Animal(name) {
  this.name = name;
  this.speed = 0;
}

// методы в прототипе
Animal.prototype.run = function(speed) {
  this.speed += speed;
  alert( this.name + ' бежит, скорость ' + this.speed );
};

При этом в первом способе можно эмулировать приватные свойства через обычные переменные. Но второй способ является более производительным. Причина проста: в первом варианте каждый раз создавая объект, мы заново определяем его «класс» (то есть все его методы и свойства). Зато во втором способе мы не можем пользоваться приватными свойствами.

Пробуя разобраться в Javascript'е, мне захотелось найти реализацию приватных свойств с прототипами. Эта идея была лишена рациональной цели. Просто захотелось. Поиски не были особо успешными, поэтому настало время самому прогуляться по граблям для постройки своего велосипеда. На ум пришел паттерн модуль:

var weekDay = function() {
  var names = ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"];
  return {
    name: function(number) { return names[number]; },
    number: function(name) { return names.indexOf(name); }
  };
}();

Приватные свойства есть, наследования нет. Тогда был написан следующий код:

let Example = (function () {
	
	let exampleProperty = 'example-property';
	
	let contstructor = function () {};
	
	constructor.prototype.exampleMethod = function () {
		console.log(exampleProperty);
	};
	
	return constructor;
	
})();

Это, в принципе, тот же модуль, только возвращает он не объект, а другую функцию (непосредственно конструктор). Это значит от «класса» Example можно без труда унаследоваться, как и сделать его наследуемым:

let Example = (function () {
	
	let exampleProperty = 'example-property';
	
	let contstructor = function () {};

      //наследуемся
       constructor.prototype = Object.create(Parent.prototype);
	
	constructor.prototype.exampleMethod = function () {
		console.log(exampleProperty);
	};
	
	return constructor;
	
})();

Все работает как надо. Желание было удовлетворено. Изучая код, после его проверки я обнаружил, что такое создание объектов даже быстрее, чем функциональный способ создания «классов». Ведь функция у нас самовызывающаяся, а значит определение методов и свойств происходит всего один раз. Хотя этот способ не быстрее обычного способа с прототипами. Позже я проверил насколько это соответствует действительности. Я сделал это достаточно топорно: запустил цикл на создание объектов и помещении их в массив и измерил с помощью console.time() в двух браузерах. Функциональный способ действительно был медленнее (порядка в десять раз), а вот мой велосипед то оставал, то перегонял родной способ на прототипах.

А теперь главный вопрос. Нужна ли приватность методов и свойств в прототипно-ориентированном языке? Кто-то говорит нет (это же не классический классовый ООП), кто-то говорит, что достаточно знака подчеркивания в начале названия, кто использует $$, а кто-то говорит, что без инкапсуляции жить нельзя. Подливают масла в огонь и сами разработчики языка, добавляя в него ключевое слово class. И пусть это синтаксический сахар над прототипами, но зачем он нужен если язык работает не на классах? В общем, ответ вопрос о необходимости приватности в Javascript для меня интересный и я хотел бы увидеть мнение в комментариях. Спасибо за внимание.

Автор: друже

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js