I have a following code:
const myFunc = () => {
let var1, var2, var3;
const setVar1 = (val) => {
var1 = val
}
return {
setVar1
}
}
Can you please tell me how this pattern is called(I read about it couple of days ago and can’t remember)?
As far as I understand, at the moment I will produce each time new object
with setVar1
method in it and if I’ll produce 1000 objects, I will get 1000 copies of setVar1
(not sure, because I have only pointer to the function)?
Can/Should I refactor this code with prototypical inheritance? Can you please explain your reasoning behind your answer, it’s very hard to understand this concept.
Thanks.
3
Answers
This is what you can do with prototypal inheritance. One of the main con is you can assign
__proto__
only one time.I don’t think you can access your
var1
orsetVar1
outside of the code ofmyFunc
because it is scoped by the language and will create new instances of it every time you run this code.What you might be looking for is an object-oriented class approach
Well, how about:
This does use prototypes, but behind the scenes. Dealing with prototypes explicitly is generally frowned upon, buf if you must:
When using closures, as in your post, all objects, including functions, are created from scratch, so yes, you’ll end up with 1000 copies of the same function.
It is true that you are creating a new
setVar()
every time you invokemyFunc()
. Due to closures,myFunc
creates a new variable, a setter function, and returns a new object everytime it is called. These look like the same, but under the hood they are not, as can be confirmed by===
, which checks for identity when comparing objects (functions are also objects). We can verify this quite directly:Try it:
With
.prototype
, whenever you do ainstance.property
lookup, JS will first search its own keys set, then its prototypes. Sincefoo
(andbar
) has no own key namedsetVar1
(the object constructed bymyFunc
has nosetVar1
, justvar1
),myFunc.prototype.setVar1
will be returned instead:Try it:
Since JS does have syntactic sugar for classes and private properties, you can and should just use that for ease of maintenance and readability:
Try it:
You can also use
Proxy
to mimic the behaviour of private properties:…or, to avoid recreating the handler object:
Try it: