Pull to refresh

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 для меня интересный и я хотел бы увидеть мнение в комментариях. Спасибо за внимание.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.