Прочитав эту статью https://www.toptal.com/javascript/es6-class-chaos-keeps-js-developer-up и впоследствии "JavaScript: The Good Parts", я буду впредь стремиться стать лучшим JavaScript разработчиком. Однако один вопрос остался для меня. Я обычно реализовывал методы, подобные этому:
function MyClass(){
this.myData = 43;
this.getDataFromObject = function(){
return this.myData;
}
}
MyClass.prototype.getDataFromPrototype = function(){
return this.myData;
}
var myObject = new MyClass();
console.log(myObject.getDataFromObject());
console.log(myObject.getDataFromPrototype());
Мое предположение, которое лежит в основе всего этого поста, заключается в том, что getDataFromObject быстрее (во время вызова, а не во время создания объекта), потому что он сохраняет косвенное отношение к прототипу, но также меньше эффективное использование памяти, потому что каждый объект получает собственный экземпляр объекта функции. Если это уже не так, пожалуйста, исправьте меня, и вы, вероятно, можете прекратить читать здесь.
Иначе: и в статье, и в книге рекомендуется такой стиль:
function secretFactory() {
const secret = "Favor composition over inheritance [...]!"
const spillTheBeans = () => console.log(secret)
return {
spillTheBeans
}
}
const leaker = secretFactory()
leaker.spillTheBeans()
(цитата из статьи, в книге еще не было ES6, но идеи похожи)
Моя проблема такова:
const leaker1 = secretFactory()
const leaker2 = secretFactory()
console.log(leaker1.spillTheBeans === leaker2.spillTheBeans) // false
Не хочу ли я в основном избегать того, чтобы каждый объект получал собственный экземпляр каждого метод? Это может быть незначительным, но если spillTheBeans более сложный, и я создаю базилион объектов, каждый из которых имеет двенадцать тысяч других методов?
Если так, что такое решение «части goot»? Мое предположение будет таким:
const spillStaticBeans = () => console.log("Tabs rule!")
const spillInstanceBeans = (beans) => console.log(beans)
function secretFactory() {
const secret = "Favor composition over inheritance [...]!"
return{
spillStaticBeans,
spillInstanceBeans: () => spillInstanceBeans(secret)
}
}
const leaker1 = secretFactory()
const leaker2 = secretFactory()
leaker1.spillStaticBeans()
leaker2.spillInstanceBeans()
console.log(leaker1.spillStaticBeans === leaker2.spillStaticBeans) // true
console.log(leaker1.spillInstanceBeans === leaker2.spillInstanceBeans) // false
Метод spillInstanceBeans по-прежнему отличается, поскольку каждый экземпляр нуждается в своем закрытии, но, по крайней мере, он просто переносит ссылку на один и тот же объект функции, который содержит всю дороговизну.
Но теперь я должен написать каждое имя метода два-три раза. Хуже того, я загромождаю пространство имен функциями publi c spillStaticBeans и spillInstanceBeans. Чтобы смягчить последнее, я мог бы написать модуль мета-фабрики:
const secretFactory = (function(){
const spillStaticBeans = () => console.log("Tabs rule!")
const spillInstanceBeans = (beans) => console.log(beans)
return function() {
const secret = "Favor composition over inheritance [...]!"
return{
spillStaticBeans,
spillInstanceBeans: () => spillInstanceBeans(secret)
}
}
}())
Это можно использовать так же, как и раньше, но теперь методы скрыты в замыкании. Однако, это становится немного запутанным. Используя модули ES6, я также мог бы оставить их в области видимости модуля и просто не экспортировать их. Но так ли это go?
Или я вообще ошибаюсь, и внутреннее представление функции JavaScript позаботится обо всем этом, и на самом деле проблемы нет?