BUT, every developer assumes he can take all of the devices' resources for his own, excluding only the operating system. That is definitely wrong. Yes, it typically only matters with thousands of object and thousands of operations etc, but you have to assume that your app is not the only thing running. Plus DOM is slow, and flashy UI's may still carry a significant computing load. It all adds up. So I'm not so sure about the memory usage anti-argument.
You can find the this factory method as Module Pattern in getify's You Dont Know JS (well… really similar) https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md#modules Ok, so the "private" variables are really nice, that's an absolute plus. On the other hand I like class better. It's cleaner, and with the arrow function I don't think it's really to complicated to solve the "this" problem. Actually the module pattern is more complicated, then using the mentioned arrow functions. You can extend classes, which is another nice feature. Also, since it's only a sugar coating for the prototype pattern you will have the luxury of prototipical inheritance. Aaaand you will use less memory too. As with frameworks, you have to find the best solution for the task.
The factory example here is not quite equivalent to the class, because it creates a new closure for every object, so it can be argued to consume more memory. To use prototypes instead, you need to do something like that:
I really appreciate this video and be convinced by factories. I'd like to spread this new way of creating object to my coworker, but I can't find out how functions can call each other.
For example : return { talk: () => console.log(sound), callMaster: () => { talk() talk() } }
I was wondering are you planning to create a paid course so we would have the opportunity to donate? I have never seen a programming video as entertaining, concise yet very clear as yours.
Instead of binding this outside the class at the click handler, can you not also bind this inside the class constructor? Would that be a better option (if you are using classes instead of factories, because reasons)? Like so: constructor() … this.talk = this.talk.bind(this)
While you've achieved private data with this pattern, it comes with an enormous memory cost. Every time you call your factory function for a new instance, it actually duplicates all those public functions as well, giving fresh copies to each new object. Not a big deal in your small example, but in larger factories called many times to produce many objects, that cost will be gargantuan. Public functions should only be created once and then shared between instances (like they are in stampit's methods({..}) object).
There is no way to achieve private data without either paying that enormous memory cost, or using ugly hacks like WeakMap that don't suffer memory issues but do have big run-time costs for the hash lookup each time. If you care about memory use and efficiency, private data is currently impossible in JavaScript.
I generally like this channel, but the performance advice was misleading IMO. The cost of instantiation is only one part of the equation, and it doesn't account for the impact on the GC. Heap usage in general will be higher, and you'd see it in slower future collection. That being said, I agree there's a threshold where it doesn't matter. I just think measuring instantiation time isn't the right metric to determine where that threshold is.
Useful video thanks 😁👍 So using the factory method each new dog created would have its own 'sound' private variable? If yes, how would you create a shared variable using a factory function? Could it be through a parameter passed into the factory?
the factory function is an example of prototypal inheritance, right? the first object we create is 'dog' with the talk method. we then create 'sniffles', which is an instance of 'dog'. when we call talk on 'sniffles', the method does not exist on 'sniffles', so the Js interpreter looks to it's prototype, which is 'dog', and there it sees the talk method, which can be called by 'sniffles'.
For the below, I need to use the this keyword… (see " this.getOscillatorConfig(oscNumber);). Or is the idea that each composed const should only have 1 function inside? Otherwise, how can I work around this?
Correct me if im wrong but another possible way of working around the lexical scope problem with "this" is assigning this into a variable and then using the variable instead like let self = this self.something = 'something'
What about an instance where I still need to have public properties? For example : Location object which has hash, query, url, host, etc.
I'd rather avoid writing get functions for all of them, and just have them be accessible right away.
In general, I can still have a factory, but create the object through Object.create({…}); instead of using thew new operator. But in this case it still instantiates a new object, where the problem with "this" would still exist, as you've shown in your example. I always solve such problems through "bind", or now through =>. But I don't necessarily see it as such a huge problem, even if it does look like a mess.
43 responses to “Factory Functions in JavaScript”
Very clear, concise, accurate and informative.
I'm sold. I'll be doing this instead of the prototype nightmare from now on.
BUT, every developer assumes he can take all of the devices' resources for his own, excluding only the operating system. That is definitely wrong. Yes, it typically only matters with thousands of object and thousands of operations etc, but you have to assume that your app is not the only thing running. Plus DOM is slow, and flashy UI's may still carry a significant computing load. It all adds up. So I'm not so sure about the memory usage anti-argument.
You can find the this factory method as Module Pattern in getify's You Dont Know JS (well… really similar)
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md#modules
Ok, so the "private" variables are really nice, that's an absolute plus. On the other hand I like class better. It's cleaner, and with the arrow function I don't think it's really to complicated to solve the "this" problem. Actually the module pattern is more complicated, then using the mentioned arrow functions. You can extend classes, which is another nice feature. Also, since it's only a sugar coating for the prototype pattern you will have the luxury of prototipical inheritance. Aaaand you will use less memory too.
As with frameworks, you have to find the best solution for the task.
great job as always !!
The factory example here is not quite equivalent to the class, because it creates a new closure for every object, so it can be argued to consume more memory. To use prototypes instead, you need to do something like that:
const dog = sound => {
const methods = {
talk: () => console.log(sound)
}
return () => Object.create(methods)
}
Besides, this factory also has the nice advantage of being more reusable as the sound is not hardcoded anymore.
weird unintuitive clown rainbow trap! 🙂
class Dog {
constructor() {
this.sound = 'woof'
}
talk = () => {
console.log(this.sound)
}
}
wouldn't that solve the problem with 'this'?
By using factories you can't take advantage of prototypes, right?
Factory functions is a pattern?
I like this.
2:28 "…unintuitive, weird, clown rainbow trap…"
hey @funfunfunction,
I really appreciate this video and be convinced by factories.
I'd like to spread this new way of creating object to my coworker, but I can't find out how functions can call each other.
For example :
return {
talk: () => console.log(sound),
callMaster: () => {
talk()
talk()
}
}
talk will be undefined just as this.talk()
Maybe I'm missing something basic.
In hope, you'll answer. :/
sniffles!!!!!!!!
me-newb: is items per Frame something we will have to worry about when building webvr webpages/apps?
How do you count method performances?
I was wondering are you planning to create a paid course so we would have the opportunity to donate? I have never seen a programming video as entertaining, concise yet very clear as yours.
world is floaking behind REACT JS ..why dont you create one video on that….
you forgot to remove your wristband from the bar last night
-_- Are you trying to give me an IP address or milliseconds? 0.0.0.4
Thank you this was a great and educational video!
How do you feel about 'stamps' ? https://github.com/stampit-org/stampit
Is a factory just another way of saying "revealing module pattern"?
Instead of binding this outside the class at the click handler, can you not also bind this inside the class constructor? Would that be a better option (if you are using classes instead of factories, because reasons)? Like so:
constructor() …
this.talk = this.talk.bind(this)
just discovered your channel. amazing! thank you!
While you've achieved private data with this pattern, it comes with an enormous memory cost. Every time you call your factory function for a new instance, it actually duplicates all those public functions as well, giving fresh copies to each new object. Not a big deal in your small example, but in larger factories called many times to produce many objects, that cost will be gargantuan. Public functions should only be created once and then shared between instances (like they are in stampit's methods({..}) object).
There is no way to achieve private data without either paying that enormous memory cost, or using ugly hacks like WeakMap that don't suffer memory issues but do have big run-time costs for the hash lookup each time. If you care about memory use and efficiency, private data is currently impossible in JavaScript.
"Clown rainbow traps" lawl
I generally like this channel, but the performance advice was misleading IMO. The cost of instantiation is only one part of the equation, and it doesn't account for the impact on the GC. Heap usage in general will be higher, and you'd see it in slower future collection. That being said, I agree there's a threshold where it doesn't matter. I just think measuring instantiation time isn't the right metric to determine where that threshold is.
Thank you a lot, I feel way less dumber than 6:33 ago lol.
Useful video thanks 😁👍 So using the factory method each new dog created would have its own 'sound' private variable? If yes, how would you create a shared variable using a factory function? Could it be through a parameter passed into the factory?
I have done it like this. I guess it is more similar to the factory function than to the class, but it is initialized as a class.
function Dog () {
const sound = 'Woof';
this.talk = () => {
console.log(sound);
}
}
const sniffles = new Dog();
sniffles.talk();
What about React? A lot of online React tutorials use classes. Is it good or bad practice?
the factory function is an example of prototypal inheritance, right? the first object we create is 'dog' with the talk method. we then create 'sniffles', which is an instance of 'dog'. when we call talk on 'sniffles', the method does not exist on 'sniffles', so the Js interpreter looks to it's prototype, which is 'dog', and there it sees the talk method, which can be called by 'sniffles'.
0.0.0.0.4 ms???? I didn't even know that was a number I'm learning so many things from these videos!!!1
The problem might be that you are creating 10,000 items per frame. lols. This show makes me smile.
Hey, what do you think about Typescript in general? Why code in Javascript at all?
For the below, I need to use the this keyword… (see " this.getOscillatorConfig(oscNumber);). Or is the idea that each composed const should only have 1 function inside? Otherwise, how can I work around this?
const oscPlayer = (audioContext, voiceConfig) => ({
getOscillatorConfig(oscNumber)
{
return voiceConfig.oscillators[oscNumber];
},
getOscillator(oscNumber)
{
this.getOscillatorConfig(oscNumber);
let vco = audioContext.createOscillator();
vco.type = oscConfig.waveform;
return vco;
}
});
const Voice = (audioContext, voiceConfig) => {
return Object.assign(
{},
oscPlayer(audioContext, voiceConfig),
octave()
)
}
There is actually just one point…
You're a great guy! Thanks so much for doing this!
Released exactly a year ago today :-).
Correct me if im wrong but another possible way of working around the lexical scope problem with "this" is assigning this into a variable and then using the variable instead like
let self = this
self.something = 'something'
r-right?
What about an instance where I still need to have public properties? For example : Location object which has hash, query, url, host, etc.
I'd rather avoid writing get functions for all of them, and just have them be accessible right away.
In general, I can still have a factory, but create the object through Object.create({…}); instead of using thew new operator. But in this case it still instantiates a new object, where the problem with "this" would still exist, as you've shown in your example. I always solve such problems through "bind", or now through =>. But I don't necessarily see it as such a huge problem, even if it does look like a mess.
This is awesome. Had a good grasp of this binding, but feels like this was the last missing piece of the puzzle.