在 Javascript 中实现私有实例变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9572029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Implementing private instance variables in Javascript
提问by SimplGy
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
我看过这篇文章,但它没有描述实现私有实例变量的最佳实践。(这甚至是我想要的名称吗?) 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
我也看过这篇文章,但我以前经常使用“this”关键字。因为它不会混淆我试图避免它。这真的是唯一的方法吗? 在原型继承中实现实例方法/变量
回答by Matt Ball
You're doing some wonky stuff with that closure. _word
needs to be declared in the Printer
function, not lost in anonymous-closure land:
你正在用那个闭包做一些奇怪的事情。_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
This keeps _word
private, at the expense of creating a new print
function on every Printer
instance. To cut this cost, you expose _word
and use a single print
function on the prototype:
这保持_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
Does it reallymatter that _word
is exposed? Personally, I don't think so, especially given the _
prefix.
暴露了真的重要_word
吗?就个人而言,我不这么认为,特别是考虑到_
前缀。
回答by Raynos
Privates are expensive, avoid them if possible
Private doesn't exist. You can do one of two things to emulate this.
私人不存在。你可以做两件事之一来模仿这一点。
- closures
- Weakmaps
- 关闭
- 弱图
Closures
关闭
function makePrinter(word) {
return {
print: function () {
console.log(word)
}
}
}
WeakMap
弱映射
Browser support for weakmapsis awful. You will probably need an emulation, I recommend pd.Name
浏览器对弱图的支持很糟糕。你可能需要一个模拟,我推荐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)
}
}
}());
Sensible objects
敏感对象
var Printer = {
constructor: function (word) {
this._word = word
},
print: function () {
console.log(this._word)
}
}
回答by Nitin Jadhav
If you are willing to use ES2015 classes (I already answered it here, but repeating for the sake of convenience),
如果你愿意使用 ES2015 类(我已经在这里回答了,但为了方便重复),
with ESNext, you can use Javascript private variableslike this:
使用 ESNext,您可以像这样使用Javascript 私有变量:
class Foo {
#bar = '';
constructor(val){
this.#bar = val;
}
otherFn(){
console.log(this.#bar);
}
}
Private field #bar is not accessible outside Foo class.
私有字段 #bar 在 Foo 类之外不可访问。
回答by nashcheez
A slight modification to the code using this
will work. The correct instance of Printer.prototype.print
was not being instantiated for the a
object.
对使用的代码稍作修改即可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