I don't know how I've missed this for so long. I've been presuming private instance variables to work like this, but they don't. They're private (as in non-global), certainly, but the variables are shared across instances. This led to some very confusing bugs.
I thought I was following the best practices implemented by some of the best libraries out there, but it seems I missed something.
var Printer = (function(){
var _word;
Printer = function(word){
_word = word;
}
_print = function(){
console.log(_word);
}
Printer.prototype = {
print: _print
}
return Printer;
})();
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Bob (!)
b.print(); //Prints Bob
I have looked at this post, but it doesn't describe a best practice for implementing private instance variables. (is this even the name of what I want?) Method and variable scoping of private and instance variables in JavaScript
I also looked at this post, but the use of the 'this' keyword is what I used to do. Because it doesn't obfuscate I was trying to avoid it. Is this really the only way? Implementing instance methods/variables in prototypal inheritance
You're doing some wonky stuff with that closure.
_word
needs to be declared in thePrinter
function, not lost in anonymous-closure land:This keeps
_word
private, at the expense of creating a newprint
function on everyPrinter
instance. To cut this cost, you expose_word
and use a singleprint
function on the prototype:Does it really matter that
_word
is exposed? Personally, I don't think so, especially given the_
prefix.If you are willing to use ES2015 classes (I already answered it here, but repeating for the sake of convenience),
with ESNext, you can use Javascript private variables like this:
Private field #bar is not accessible outside Foo class.
Privates are expensive, avoid them if possible
Private doesn't exist. You can do one of two things to emulate this.
Closures
WeakMap
Browser support for weakmaps is awful. You will probably need an emulation, I recommend pd.Name
Sensible objects
A slight modification to the code using
this
will work. The correct instance ofPrinter.prototype.print
was not being instantiated for thea
object.