我正在尝试在JS中使用Closure,以便声明一个名为**expandArray()**
的函数,其中包含一个名为**myArray**
的数组,并返回一个直接修改 myArray 的匿名函数。通过将值比返回的函数增加1,然后返回**myArray**
的值。我的问题在这里,最后一部分是返回的函数返回的函数不是数组值?!
这是我的代码
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray());
答案 0 :(得分:3)
作为其闭包,您只能像expandArray()
一样调用它一次,它返回下面的函数本身
ƒ () {
myArray.map( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
}
you need to invoke it again to get your result back
如下
expandArray()() //[2, 2, 2]
答案 1 :(得分:1)
您编写了一个函数,该函数在运行时返回一个函数:
function expandArray() {
const myArray = [...];
// return this when we run expandArray():
return function() {
...
}
}
因此,如果您运行expandArray()
,它将返回您的匿名函数。完全像您写的那样。
如果您随后想要获得对该内部myArray
的实际引用,则现在需要实际运行返回了函数的 ,因此:
var getMyArray = expandArray();
var result = getMyArray();
console.log(result);
答案 2 :(得分:1)
在原始代码中,您仅获得expandArray()
的返回值,这是您试图用作闭包的函数。为了获得闭包的返回值,请尝试以下操作:
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray()());
调用expandArray()
之后的第二组括号将调用闭包并返回您要查找的值。
答案 3 :(得分:1)
仅供参考,您所做的事情与memoization pattern非常相似。
要解决您的问题:正如其他人已经说过的那样,您从expandArray
返回了一个函数。您想要的是返回封闭的数组(在增加每个元素之后)。
为此,您可以结合使用immediately-invoked function expression和箭头功能来简化代码:
const expandArray = (() => {
const myArray = [1, 1, 1];
return () => {
myArray.forEach((num, index) => {
myArray[index] = num + 1;
});
return myArray;
};
})();
console.log(expandArray());
console.log(expandArray());
console.log(expandArray());
答案 4 :(得分:1)
您的代码有些错误。
您不能更改在const中声明的变量的值。对于对象和数组,不允许使用新的数组或对象分配新的引用。我们将声明性运算符更改为let
而不是const
。
myArray.map
不会突变myArray,它会基于myArray
的输入以及您传入的函数(每个值加1)返回一个新数组。我们可以通过将myArray.map
分配给已经声明的myArray
来解决此问题。也就是说,我们正在用新阵列覆盖旧阵列。这就是为什么上述要点中的const
无法正常工作的原因。
您的map
函数参数不是必需的。最常用的参数是前两个可用参数,即该项目的item in the array
和index
。由于我们使用map
遍历每个数字,因此该函数可以简单地返回item
(在您的代码中声明为 num )加1。这将返回一个包含以下内容的新数组您更改的值。因此,我们根本不需要index
。
从函数返回一个函数时,您需要同时调用这两个函数以获得第二个返回值。使用闭包时,您需要保留对初始返回函数的引用。这很令人困惑,但是如果您将其视为级别-在expandArray
函数中,您有两个级别。函数本身和要返回的函数。当您调用expandArray()
时,您正在调用第一级,并使第二级可被调用,这就是expandArray()
返回第二个函数而expandArray()()
将从第二个函数返回值的原因。第二功能。通过将返回的函数设置为等于add_to_array
,将返回的函数保存在名为expandArray()
的变量中,然后我们一致地调用add_to_array
以返回具有更改后的值的新Array。
add_to_array
变量就像函数中的楔形。它阻止myArray
被浏览器删除,因为它要求函数在再次需要调用时存在。有点像一本书中的书签。为了使故事在每次打开时都有意义,您不仅要撕掉书签之前的页面。您可以使故事保持原样,因为在回到故事的五年中,您可能需要阅读书签中的前几页以记住您的位置。闭包的工作方式相同。它无法从最初的expandArray
函数调用中删除变量,因为add_to_array
是中间的占位符。参考点使书保持打开状态。
(有关封包的更多信息,您可以在Destroying Buildings - A Guide to JavaScript Closures处查看此文章)
function expandArray() {
let myArray = [1, 1, 1];
return function () {
myArray = myArray.map( function (num) {
return num + 1;
});
return myArray;
};
}
let add_to_array = expandArray();
console.log( add_to_array(),add_to_array(),add_to_array() );
答案 5 :(得分:0)
旧帖子,但我仍然想贡献。我想出了这个解决方案,因为我想您要向数组中添加一些内容,而不是增加数字。
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1)
return myArray
}
}
const array = expandArray();
const result = array();
console.log(result)