当我引用全局变量时,为什么闭包不能反映对原始变量的更改?

时间:2015-09-08 05:06:28

标签: javascript

在我正在开发的应用程序中,我定义了一个全局App命名空间,其中我存储了一些我想从不同函数访问的属性。例如,我可能会在我的全局menuOpen命名空间中保存一个菜单App属性,因此我用来处理Menu接口功能的函数可以使用处理其他内容的其他函数轻松共享此信息。

我刚才遇到这个问题,用一个函数更新这个全局变量,然后在另一个函数的闭包中检查引用,找到引用didn'反映我的变化。

我在一个简单的例子中重新创建了这个,我希望false成为结果,因为baropen更改为false,应该反映出来在state关闭之前foo内的state完成并对//set a global variable to be accessed by different parts //of an application var open = true; //create a closure, which waits for a future event, //then checks the "open" variable when it occurs function foo() { //reference to the global variable "open" var state = open; //set a timeout, to reflect "a future event", such //as an event handler setTimeout(function() { if (state) { $('html').text('true'); } else { $('html').text('false'); } }, 1000); } //change the "open" global within another function function bar() { open = false; } //create the closure foo(); //change "open" to false, before the "if(state)" logic //is called in the closure bar();进行检查:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
state

我的理解是闭包会保留对变量的引用,因此open会反映对foo的任何更改。这实际上是如何工作的?我需要做些什么才能让open的闭包知道var time = '00 : 15 . 13' // Example time format $.ajax({ type: 'POST', url: '/time', dataType: 'json', data: { time: time } }) 的变化?

2 个答案:

答案 0 :(得分:2)

这与闭包无关。 var x = "a"; var y = x; x = "b"; console.log(y)输出"a",而非"b",因为yx的副本。

闭包不会改变变量的正常行为。闭包只是一个使用周围范围的局部变量的函数。 foo是一个闭包,因为它使用open;传递给setTimeout的函数是一个闭包,因为它使用state(但state在设置后永远不会改变。)

您可以直接查看if (open)来修复您的代码。

答案 1 :(得分:0)

正如其他人所说,这个问题与闭包没有任何关系。它与Javascript如何分配不同类型有关。

只有Javascript中的对象由指针指定。所有其他数据类型都按值分配(例如,复制值)。所以,当你这样做时:

var state = open;

而且,open不是一个对象(包括对象,数组和函数),然后open中的值被复制到state,然后两个变量都没有彼此做。

见这个例子:

var myNum = 12;
var otherNum = myNum;
document.write("myNum = ", myNum, "<br>");          // 99
document.write("otherNum = ", otherNum, "<br>");    // 12

myNum = 99;
document.write("myNum = ", myNum, "<br>");          // 99
document.write("otherNum = ", otherNum, "<br>");    // still 12

但是,如果您分配了一个对象,它只是一个指向原始对象的指针,因此如果原始对象发生了更改,您会看到对该对象的另一个引用中的更改:

function log(name, obj) {
    document.write(JSON.stringify(obj) + "<br>");
}

var myObj = {greeting: "hello"};
var otherObj = myObj;
log("myObj", myObj);
log("otherObj", otherObj);

myObj.greeting = "bye";
log("myObj", myObj);
log("otherObj", otherObj);

通过指针指向原始对象。所有其他类型的变量的行为就像复制它们并且不再与原始变量连接一样。

如果你想获取一个普通的非对象变量并让它表现得像你有一个指向它的指针,那么你可以将该变量作为该对象的属性放入一个对象中,你可以传递该对象。然后,您传递对象的每个人都可以检查该属性,并且他们将查看完全相同的属性值。如果一个人改变它,他们都会看到改变的值。