Let’s say I were to write a class (this has no literal meaning I’m just writing some BS)
class A {
constructor(name, date) {
this.nameDateString = name + date;
}
someMethod() {
return `${this.nameDateString} ${this.nameDateString}`;
}
addAnotherNameDateString(name, date) {
this.nameDateString += name + date;
}
}
Would writing a function that creates a closure (am I using this term right?) on some data by defining some functions and returning them:
const createA = (name, date) => {
let nameDateString = name + date;
const someMethod = () => {
return `${nameDateString} ${nameDateString}`;
}
const addAnotherNameDateString = (name, date) => {
nameDateString += name + date;
}
return { someMethod, addAnotherNameDateString };
}
be less efficient in terms of memory?
For example, would
Array(100000).fill(null).map((_, i) => new A(i, new Date() + i*123456))
be more advantageous than:
Array(100000).fill(null).map((_, i) => createA(i, new Date() + i*123456))
>Solution :
Just up front: Programming using a style with createA or similar is quite common; it’s one of the popular ways is JavaScript is used. Programming with class A or similar is also quite common, and one of the (perhaps slightly more) popular ways JavaScript is used.
Would [creating different functions each time] be less efficient in terms of memory?
Yes, a bit. But whether that matters is another thing entirely, relative to other objective/concerns.
With your class, the function objects for the methods are on A.prototype and are reused by each instance of the class (they’re inherited from the prototype assigned to them):
class A {
constructor(name, date) {
this.nameDateString = name + date;
}
someMethod() {
return `${this.nameDateString} ${this.nameDateString}`;
}
addAnotherNameDateString(name, date) {
this.nameDateString += name + date;
}
}
const a1 = new A("joe", new Date());
const a2 = new A("joe", new Date());
console.log(a1.someMethod === a2.someMethod); // true
With your createA function, different function objects for those methods are created every time createA is called:
const createA = (name, date) => {
let nameDateString = name + date;
const someMethod = () => {
return `${nameDateString} ${nameDateString}`;
}
const addAnotherNameDateString = (name, date) => {
nameDateString += name + date;
}
return { someMethod, addAnotherNameDateString };
}
const a1 = createA("joe", new Date());
const a2 = createA("joe", new Date());
console.log(a1.someMethod === a2.someMethod); // false
So the objects created by createA have a larger memory imprint than the objects created by new A, because they have their own copies of those function objects.
But function objects aren’t that big (the underlying code is reused by all the functions; it’s just the function objects that are distinct from each other). So if the createA style fits your goals better than the class A style, or vice-versa, use the one that fits your goals.
The size difference is unlikely to matter for 100,000 instances (even on mobile devices; but certainly it might in an embedded environment). But if you’re in the millions, you may well need to start thinking about avoiding memory pressure.
If you’re worried about the memory impact, measure it with your real code. In major browsers, you can use a Memory tab in the dev tools to help you measure the impact of your code choices on memory consumption.