模块中未更新Nodejs闭包变量
Nodejs closure variable not updated in module
我需要一些帮助来理解NodeJ。我显然错过了一些基本的东西。我有一个类似于下面的模块,使用了一个基本的揭示模块模式。。。
var someArray = [];
var publicApi = {
someArray: someArray,
someFunction: someFunction
};
function someFunction() {
someArray = ['blue', 'green'];
}
module.exports = publicApi;
当我使用这个模块时,当我调用someFunction时,someArray不会改变。。。
var myModule = require('myModule');
myModule.someFunction();
var test = myModule.someArray;
// test is always an empty array
请帮我理解原因。我意识到我可能可以使用构造函数来实现这一点,但我想填补我对为什么上述方法不起作用的认识空白。
更新:
我可以通过对模块进行以下修改来实现这一点。。。
var theModule = {
someArray: [],
someFunction: someFunction
};
function someFunction() {
theModule.someArray = ['blue', 'green'];
}
module.exports = theModule;
但我仍然想弄清楚为什么第一个模块中的代码不起作用。我正在处理的模块作为一个单例是很好的,所以我很想看看在模块中设置变量的最佳实践是什么,这些变量可以被该模块中的函数更改,并且可以在该模块之外公开访问。
第一种方法不起作用的原因与没有Node的情况下在JavaScript中不起作用相同:
var someArray = [];
var object = {
someArray: someArray,
}
someArray = [1, 2, 3];
console.log(object.someArray);
这将打印[]
,因为object.someArray
是对您创建的第一个数组的引用。这就是过程:
var someArray = [];
创建一个空数组,然后将对该数组的引用保存为名称someArray
。让我们称之为array1
。
var object = {
someArray: someArray
}
创建一个属性为someArray
的对象,使该属性引用someArray
引用的数组。重要的是要知道,这意味着这个引用现在是对array1
的引用,而不是对someArray
的引用。这将我们引向:
someArray = [1, 2, 3];
它创建了一个新的数组(我们称之为array2
),然后将其存储为someArray
。此数组完全独立于array1
,并且someArray
的所有未来引用都将获得array2
,但它对以前的访问没有影响。
这与Node示例的工作原理完全相同——当覆盖someArray
而不是publicApi.someArray
时,不会对publicApi.someArray
进行任何更改,因此不能期望它有所不同。
希望能明确这一点,你可以从以下方面着手:
someArray -> array1[]
object.someArray -> array1[]
对此:
someArray -> array2[1, 2, 3]
object.someArray -> array1[]
请注意,object.someArray
没有变化。
您认为这是一个对象,而不是一个闭包。当函数有权访问特权数据时,就会产生闭包。也就是说,数据绑定从程序的其余部分"消失"。这里有一个例子:
function SomeFunction(x) {
var closureVar = x;
toReturn = function(y) {
var answer = closureVar;
closureVar = y;
return answer;
}
return toReturn;
}
var runIt = SomeFunction(15);
实际情况是,当调用SomeFunction时,它会为"closureVar"创建一个本地绑定。当一个函数退出时,它的所有本地绑定(通常)都会消失。但是,在这种情况下,返回的函数包含对"closureVar"的引用,因此无法完全删除。因此,定义为"toReturn"的函数仍然可以使用它
然而,程序中没有其他东西可以访问它。如果您再次调用SomeFunction(),它将为closureVar创建一个新的(本地)绑定,该绑定将由该调用SomeFunction()所提供的toReturn函数使用。对SomeFunction()的每次调用都会产生一个新的闭包。
FWIW,如果你这样做,它确实有效:
function someFunction() {
//someArray = ['blue', 'green'];
someArray[0] = 'blue'
someArray[1] = 'green'
}
我认为这意味着当你用[]创建一个新数组时,你不知何故破坏了引用链。我的理解还不足以说明。
访问模块内变量的最佳实践可能是定义get/set方法:
var someArray = [];
var publicApi = {
getSomeArray: function () { return someArray; },
setSomeArray: function (s) { someArray = s; },
/*
* Or if you know you can support get/set syntax:
*
* get someArray () { return someArray; }
* set someArray (s) { someArray = s; }
*/
someFunction: someFunction
};
function someFunction() {
someArray = ['blue', 'green'];
}
module.exports = publicApi;
获取并设置MDN上的语法定义。
但是,如果您确实希望直接访问对象本身,请使用您提到的模块名称空间:
theModule.someArray = ['blue', 'green'];
但是,您看到的问题是因为您正在用新阵列进行替换,而不是修改阵列,例如
function someFunction() {
someArray.splice(0);
someArray.push('blue', 'green');
}
我认为赋值会导致创建一个新的对象引用,而修改现有对象会维护现有引用。
这是共享呼叫的结果:
JavaScript是一种传递引用语言还是传递值语言
https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing
- 子类访问父类's闭包变量
- 构造函数函数闭包变量
- 如何冻结函数's在闭包中的变量
- 使变量可用于不带闭包的异步调用
- 局部变量在闭包中丢失
- 其中是闭包中存储的变量-堆栈或堆
- javascript闭包:保护内部变量
- Javascript:附加字符串中的事件,闭包中的变量求值
- "可变变量可从闭包“”访问;在传递给Array.prototype.every的函数中
- JavaScript闭包和变量引用
- Javascript分析之谜 - 闭包变量
- 对闭包变量的更改是否在使用闭包的回调中可见
- 使用object.assign()添加到对象中的getter发现闭包变量的值错误
- Javascript:为什么对闭包变量的访问可能很慢
- 模块中未更新Nodejs闭包变量
- node.js捕获闭包变量
- Javascript中绑定闭包变量
- 函数外部的Javascript闭包变量访问
- 回调函数访问闭包变量
- 为什么我的闭包变量在使用$后被清除.每个都使用JSON数据