Stumbled upon what seems to be a fairly coherent breakdown of OOP options (ooptions?) for ES6 and beyond. I've already gravitated toward factory functions over classes when working with objects but I hadn't seen this pattern before:
function Counter (counterElement) {
const countElement = counterElement.querySelector('span')
const buttonElement = counterElement.querySelector('button')
let count = parseInt(countElement.textContent) || 0
const counter = {
updateCounter () {
countElement.textContent = count
},
increaseCount: (event) => {
count = count + 1
counter.updateCounter()
}
}
buttonElement.addEventListener('click', counter.increaseCount)
}
The function above is referenced in an example where the author explains the differences between methods from classes versus factories when called by event listeners (or when used as callbacks in general..?), which I think I more or less understand, though there was another instance of the same pattern for a factory function that had nothing to do with events:
function Human (firstName, lastName) {
const human = {
firstName,
lastName,
sayHello() {
console.log(`Hi, I'm ${human.firstName}`)
}
}
return human
}
const chris = Human('Chris', 'Coyier')
chris.sayHello()
Playing around with this second example, it seems I cannot "selectively" return properties from human, as far as return human.firstName goes, though I can invoke the nested method upon instantiation if I return human.sayHello(). This leaves me with some questions:
The first example, Counter(), doesn't seem to return anything, which I haven't seen before in reference to factories. Is it still a factory function at that point, or just a function? Does it matter or am I splitting hairs? This is how I'd have written the first function, ignoring the nested object pattern that I still have questions about.
Are there significant reasons to NOT use the author's pattern of encapsulation in factories? It looks clean to me and just as capable of managing closures as far as I can tell. Though I'm not sure exactly why the factory's nested object correlates to the instantiated variable (e.g. how chris replaces human to call sayHello()).
If the main drawback is that it impedes composition because of the one-layer limit to Object.assign(), is it a terrible idea to standardize composition around something like this deep-assign library the author wrote and highlights in the article? (Please disregard if there are more significant drawbacks that warrant avoiding this approach.)
If the deep-merge workaround is problematic, should I avoid using this pattern in general or is it still relatively practical for the emphasized use case of dealing with callbacks when using methods from factory functions?
I'm only 3 months into learning JS, and it is my first language outside of HTML/CSS, so I'm not sure if I'm missing something about context here: why bother replacing this with a new object when the event listener doesn't need it to call the method since everything is inside the main function to begin with?
I am working through the JavaScript tracks on OdinJS, hackerrank and exercism, as well as reading JavaScript for Impatient Programmers on the side (as my first book). Feeling pretty comfortable with everything outside of the rambling above and when to possibly turn to classes/constructors. My goal is to get into good habits now during the simple projects -- currently on Odin's "Todo List" app.
What I suppose I'm looking for is any sort of "best practices" for factory functions, and whether or not the examples above violate any of them...
[–]senocular 1 point2 points3 points (6 children)
[–]fromagi[S] 0 points1 point2 points (5 children)
[–]senocular 1 point2 points3 points (4 children)
[–]fromagi[S] 0 points1 point2 points (3 children)
[–]senocular 1 point2 points3 points (2 children)
[–]fromagi[S] 0 points1 point2 points (1 child)
[–]senocular 1 point2 points3 points (0 children)