Javascript:在闭包中,可以在实例化后添加私有成员(var`s)吗?
实例化后能否将“私有”成员(VAR)添加到闭包中 我想我在下面的结束语中理解了这一点(如果我错了,请纠正我!):Javascript:在闭包中,可以在实例化后添加私有成员(var`s)吗?,javascript,closures,Javascript,Closures,实例化后能否将“私有”成员(VAR)添加到闭包中 我想我在下面的结束语中理解了这一点(如果我错了,请纠正我!): 此.x可“公开”使用 var y公开不可用,但可以通过此.y()访问 在newclosure()之后,我可以添加一个新的“public”,如下所示: var c=new Closure(); c['z']=25; console.log(c.z); // z is a dynamically added public member 那么……有没有办法在“新建”闭包后动态添加
可“公开”使用此.x
公开不可用,但可以通过此.y()访问var y
- 在
之后,我可以添加一个新的“public”,如下所示:newclosure()
var c=new Closure(); c['z']=25; console.log(c.z); // z is a dynamically added public member
var Closure=( function(){
function Closure(x){
// "public" member
this.x=x;
};
// "private" member backing variable
var _y=0;
// get/set private member
Closure.prototype.y=function(newValue){
if(newValue){
_y=newValue;
return(this);
}else{
return(_y);
}
};
// return
return(Closure);
} )();
var c=new Closure(10,15);
// Can I add var _z and it's get/set function at this point?
对。某种程度上。您可以创建私有对象或数组,并提供添加到其中的方法 使用
WeakMap
:
function myClosure() {
var hidden = new WeakMap();
var obj = {
addPrivate: function(name, value) {
var privateData = hidden.get(this);
privateData[name] = value;
}
}
hidden.set(obj, {});
return obj;
}
var foo = myClosure();
foo.addPrivate('bar', 7);
foo.getBar = function() {
var priv = hidden.get(this);
return priv.bar;
}
foo.getBar(); //7
一个更好的问题是你应该这样做吗?一般来说,答案是否定的。我认为唯一值得考虑的是,当我有一个应用程序核心对象时,我会用异步扩展脚本逐步增强它(我使用<代码> WeakMap <代码>表格,如果我不需要担心旧浏览器,如果我使用嵌套的Obji文字)。
var y
不可公开使用
对
但是可以通过this.y()访问
否。此
通常是一个对象,.y
始终是一个属性引用。它永远不能用于访问y
变量
有没有一种方法可以在“新建”闭包后动态添加私有成员(var)及其get/set函数
否。当调用了Closure()
函数(在您作为构造函数的情况下)时,它与所有变量(x
)的作用域已确定,并且无法修改
同样的事情也适用于IIFE,IIFE的执行引入了本地闭包
和\u y
变量,这些变量随后被解决
但是,您可以添加一个新的getter/setter对,它有自己的作用域(可能有额外的“私有”变量),但不可能从外部访问\y
变量或操作它所在的作用域
function Scope(x, y) {
// "public" member
this.x = x;
// private "member"
var _y = y;
// accessors:
this.setY = function(newValue) { _y = newValue; };
this.getY = function() { return _y; };
// '_y' is still accessible here ^^
// through closure of the two functions, which can access their parent scope
}
var c = new Scope(10, 15);
c.x // 10
c.getY() // 15
此处无法修改\u y
(和x
和y
)所驻留的范围。但是,我们可以向c
添加一个新字段,即使其变量不在同一范围内:
function addZ(obj, z) {
// new scope, private variable:
var _z = z;
obj.getZ = function() { return _z; }
// setter analogous if you want one
}
addZ(c, 12);
c.getZ() // 12
是的,你可以。只需创建一个新闭包,并在对象上添加私有变量的getter/setter函数。然而,新的私有变量将只在新的闭包中。它不会在旧的关闭。不管怎样,你的用例是什么?@AaditMShah。感谢您的回复!那么,我如何在运行时动态地将var z
添加到闭包中(请原谅我的“noobiness”)?我将我的用例描述为“动态继承”。我想从一个基闭包开始,根据需要动态添加成员(public和private)。然而,您真的需要私有变量吗?考虑一下:您已经让程序员使用getter和setter获取并设置z
的值。那么为什么不公开呢?此外,继承和OOP并不是99%用例的解决方案。你应该看看代数数据类型:你的第一个代码片段给我一个语法错误:在(var bar=7)中的索引1处;“:预期表达式,得到关键字'var'
即使你解决了这个问题,这也会创建一个全局bar
变量,或者你的getBar
函数不起作用。不,它不起作用。您创建的条
存在于addPrivate
的范围内,而不在myClosure
中。这两个作用域都不能被getBar
函数访问,这应该会引发一个引用错误。如果没有,这意味着你有一个全局条
;请使用干净的全局范围重试。我删除了我的评论,因为您是正确的。道歉。不正确,如果这些私有变量是数据结构,并且您提供了访问闭包的访问器方法,那么它就可以正常工作。您还可以使用eval()
来欺骗词法范围。您是否应该做这两件事是另一回事。@JaredSmith:变量不是数据结构,而是变量。当然,如果它包含一个结构,您可能可以修改该结构,但是如果没有允许您这样做的显式闭包,您就无法访问/设置该变量eval
可以用于许多有趣的事情,但是你不能用它来修改已经存在的作用域(除了“current”,但那不有趣),我明白了…所以闭包在实例化之后不会接受新的var
s。因此,为了模拟动态添加的变量,您是否支持保存键值对的私有对象文本的概念。当需要新的“private”时,只需在private对象文本上推送一个新的键值,并使用getter/setter获取任何指定的键值。这类似于asp.net MVC中的ViewBag。还是有更好的方法?@JustAsking:嗯,通常你不需要动态地使用私有字段,尤其是在没有任何东西使用它们的情况下。但是,如果您想为它们创建新的访问器,您可以为它们创建一个新的私有变量——它不需要绑定到构造函数创建的范围。我用一个例子更新了我的答案