我需要一些帮助来理解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;
但我仍然想明白为什么第一个模块中的代码不起作用。我正在处理的模块很好,作为一个单例,所以我很乐意看到在模块中有变量的最佳实践,可以通过该模块中的函数进行更改,并且可以公开访问在那个模块之外。
答案 0 :(得分:2)
你第一次使用它的方法不起作用的原因与在没有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
未更改。
答案 1 :(得分:0)
你正在考虑这个问题,好像它是一个对象而不是一个闭包。当函数可以访问特权数据时,会产生闭包。也就是说,数据绑定"消失"从该计划的其余部分。这是一个例子:
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()都会产生一个新的闭包。
答案 2 :(得分:0)
FWIW,如果你这样做,它确实有效:
function someFunction() {
//someArray = ['blue', 'green'];
someArray[0] = 'blue'
someArray[1] = 'green'
}
我认为这意味着当你使用[]创建一个新数组时,你会以某种方式打破引用链。我的理解还不够好。
答案 3 :(得分:0)
访问模块中变量的最佳做法可能是定义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');
}
我相信赋值会导致创建新的对象引用,而修改现有对象则会保留现有引用。
这是分享呼叫的结果:
Is JavaScript a pass-by-reference or pass-by-value language?
https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing