我不知道我多久都错过了这个。我一直假设私有实例变量像这样工作,但他们没有。当然,它们是私有的(如非全局的),但变量是跨实例共享的。这导致了一些非常混乱的错误。
我以为我正在遵循一些最好的图书馆实施的最佳做法,但似乎我错过了一些东西。
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
我看过这篇文章,但没有描述实现私有实例变量的最佳实践。 (这甚至是我想要的名字吗?) Method and variable scoping of private and instance variables in JavaScript
我也查看了这篇文章,但使用'this'关键字是我以前做的。因为它没有混淆我试图避免它。这真的是唯一的方法吗? Implementing instance methods/variables in prototypal inheritance
答案 0 :(得分:28)
你正在做那些关闭的好东西。 _word
需要在Printer
函数中声明,而不是在匿名封闭的土地上丢失:
function Printer(word) {
var _word = word;
this.print = function () {
console.log(_word);
}
}
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Alex
b.print(); //Prints Bob
这会使_word
保密,但会牺牲在每个print
实例上创建新的Printer
函数。要降低此费用,您需要公开_word
并在原型上使用单个print
函数:
function Printer(word) {
this._word = word;
}
Printer.prototype.print = function () {
console.log(this._word);
}
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Alex
b.print(); //Prints Bob
就个人而言,我不这么认为,特别是考虑到
_word
前缀。
答案 1 :(得分:13)
Privates are expensive, avoid them if possible
私人不存在。你可以做两件事之一来模仿这个。
function makePrinter(word) {
return {
print: function () {
console.log(word)
}
}
}
浏览器对weakmaps的支持非常糟糕。您可能需要进行模拟,我建议pd.Name
var Printer = (function () {
var privates = function (obj) {
var v = map.get(obj)
if (v === undefined) {
v = {}
map.set(obj, v)
}
return v
}, map = new WeakMap()
return {
constructor: function (word) {
privates(this).word = word
},
print: function () {
console.log(privates(this).word)
}
}
}());
var Printer = {
constructor: function (word) {
this._word = word
},
print: function () {
console.log(this._word)
}
}
答案 2 :(得分:0)
使用this
对代码稍作修改即可。没有为Printer.prototype.print
对象实例化a
的正确实例。
var Printer = (function(){
var _word;
Printer = function(word){
this._word = word;
}
_print = function(){
console.log(this._word);
}
Printer.prototype = {
print: _print
}
return Printer;
})();
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Alex
b.print(); //Prints Bob
答案 3 :(得分:0)
如果您愿意使用ES2015类(我已经here回答过,但是为了方便起见重复),
通过ESNext,您可以像这样使用Javascript private variables:
class Foo {
#bar = '';
constructor(val){
this.#bar = val;
}
otherFn(){
console.log(this.#bar);
}
}
在Foo类之外无法访问私有字段#bar。