Javascript:在闭包中,可以在实例化后添加私有成员(var`s)吗?

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 那么……有没有办法在“新建”闭包后动态添加

实例化后能否将“私有”成员(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
    
那么……有没有办法在“新建”闭包后动态添加私有成员(var)及其get/set函数?

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:嗯,通常你不需要动态地使用私有字段,尤其是在没有任何东西使用它们的情况下。但是,如果您想为它们创建新的访问器,您可以为它们创建一个新的私有变量——它不需要绑定到构造函数创建的范围。我用一个例子更新了我的答案