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

Javascript: In closures, can private members (var`s) be added after instantiation?

本文关键字:实例化 添加 var 成员 闭包 Javascript      更新时间:2023-09-26

实例化后是否可以将"私有"成员(vars)添加到闭包中?

我想我在下面的结束语中理解了这一点(如果我错了,请纠正我!):

  • this.x可"公开"

  • var y不可公开使用,但可以通过该.y()访问

  • new Closure()之后,我可以添加一个新的"公共",如下所示:

    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?

var y无法公开

但可以通过this.y() 访问

没有。this通常是一个对象,而.y始终是属性引用。它永远不能用于访问y变量

有没有一种方法可以在"新建"闭包之后动态添加私有成员(var)及其get/set函数?

没有。当Closure()函数被调用(在您的情况下是构造函数)时,它与所有变量(x)的作用域将被确定,并且不能被修改。

IIFE也是如此,它的执行引入了本地Closure_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

这里没有办法修改_y(以及xy)所在的范围。然而,我们可以向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

是。有点。你可以创建一个私有对象或数组,并提供添加到其中的方法

使用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形式,如果我这样做了,我就会使用嵌套的obj文字)。