对JavaScript闭包的误解

对JavaScript闭包的误解,javascript,closures,Javascript,Closures,我是JavaScript新手,理解此代码时遇到问题: function addProperty(o) { var value; o["get"] = function() { return value; } o["set"] = function(v) { value = v; } } var a = {}; addProperty(a); var b = {}; addProperty(b); a.set(4); b.set(5); print("a is " + a

我是JavaScript新手,理解此代码时遇到问题:

function addProperty(o) {
   var value;

   o["get"] = function()  { return value; }
   o["set"] = function(v) { value = v; }
}

var a = {};
addProperty(a);
var b = {};
addProperty(b);

a.set(4);
b.set(5);
print("a is " + a.get() + "; b is " + b.get());

这将打印(在v8/d8中)
a为4;b是5
。如果我注释掉
var值行,我得到
a是5;b是5
。“值”对象在哪里?为什么有两个?谢谢。

变量是
addProperty
的本地变量。第一次调用
addProperty
时,将创建一个新的
,在该值上两个函数都将关闭。第二次调用
addProperty
时,将创建第二个
,在该值上关闭两个新函数

删除
var
会在
窗口
对象上创建一个由所有函数共享的全局

也许你的意思是:

function createPropertyMgr() {
    var value;
    return function(o) {
       o["get"] = function()  { return value; }
       o["set"] = function(v) { value = v; }
    }
}

var addProperty = createPropertyMgr();

无论调用多少次,这个新的
addProperty
函数都会关闭一个
值。我不确定我是否理解这个用例,但这应该说明区别。

当您没有在函数中显式声明变量时,它的作用域被假定为全局变量。i、 e.在第二种情况下,由于您没有将
value
明确声明为函数
addProperty()
的本地,因此它被视为全局


但当您在函数中显式声明它时,它将成为函数的局部。每次调用函数时,都会在堆栈上创建函数局部变量的新副本(重要的是,只要有对它的引用,它就会留在堆栈中)

我不理解问题的“为什么有两个”部分。您能澄清一下吗?对象“a”有一个与之关联的值,它包含整数“4”,对象“b”有一个与之关联的值,它包含整数“5”。+1源代码中有一个
值,但内存中有两个。这似乎是OP的混乱之处。因此,它在每个addProperty调用上创建一个value var副本。但是,如何将其绑定到参数对象?@TomasNarros:同样的方式。使用
var
声明的形式参数、函数声明和变量都是“激活对象”的一部分,即,复制它以创建词法闭包。@TomasNarros-每次调用
addProperty
时,都会为传入该闭包的对象创建一对新的
get/set
函数。好的,我明白了-谢谢。我只是想问另一个问题,这就是促使这一问题的原因,关于一般的封装。