1

我正在尝试在 JS 中使用 Closure 来声明一个名为的函数,该函数**expandArray()**包含一个名为**myArray**并返回一个匿名函数,该函数通过将值增加 1 而不是返回的函数然后返回的值来直接修改myArray**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());
4

6 回答 6

3

作为它的闭包,你只调用了一次 like 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]

参考:JavaScript 闭包是如何工作的?

于 2018-07-27T16:23:22.297 回答
1

您编写了一个函数,它在运行时返回一个函数:

function expandArray() {
  const myArray = [...];
  // return this when we run expandArray():
  return function() {
    ...
  }
}

因此,如果您运行expandArray(),它将返回您的匿名函数。就像你写的那样。

如果您想获得对该 internal 的实际引用myArray,您现在需要实际运行该返回的 function,因此:

var getMyArray = expandArray();
var result = getMyArray();
console.log(result);
于 2018-07-27T16:20:48.580 回答
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()将调用闭包并返回您正在寻找的值。

于 2018-07-27T16:22:12.767 回答
1

仅供参考,您正在做一些与记忆模式非常相似的事情。

为了解决您的问题:正如其他人已经说过的,您从expandArray. 您想要的是返回封闭数组(在增加每个元素之后)。

为此,您可以结合使用称为立即调用函数表达式的箭头函数来简化代码:

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());

于 2018-07-27T16:30:43.583 回答
1

您的代码有几处不正确。

  • 您不能更改在 const 中声明的变量的值。在对象和数组的情况下,您不能用新的数组或对象分配新的引用。我们将声明性运算符更改为let而不是const

  • myArray.map不会改变 myArray,它会根据输入myArray和您传入的函数返回一个新数组,该函数将每个值加 1。我们可以通过分配myArray.map给已经声明的myArray. 也就是说,我们正在用新的 Array 覆盖旧的 Array。这就是为什么const上面的要点不起作用。

  • 您的map函数参数是不必要的。最常用的参数是前两个可用的,即该项目的 theitem in the array和 the indexmap由于我们使用该函数迭代每个数字,因此可以简单地返回item(在您的代码中声明为num)加 1。这将返回一个包含更改值的新数组。所以我们根本不需要index..

  • 当你从一个函数返回一个函数时,你需要调用两者来获得第二个返回值。使用闭包时,您需要保留对初始返回函数的引用。这很令人困惑,但是如果您将其视为级别 - 在您的expandArray函数中,您有两个级别。函数本身和您要返回的函数。当您调用时,expandArray()您正在调用第一级,并使第二级可供调用,这就是expandArray()返回第二个函数并将expandArray()()返回第二个函数的值的原因。我们将返回的函数保存在一个add_to_array通过将其设置为调用的变量中expandArray(),然后我们始终调用add_to_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() );

于 2018-07-27T16:34:38.447 回答
0

旧帖子,但我仍然喜欢贡献。我想出了这个解决方案,因为我认为您想在数组中添加一些东西而不是增加数字。

function expandArray() {
    let myArray = [1, 1, 1];

    return function() {
        myArray.push(1)
        return myArray
    }
}

const array = expandArray();
const result = array();
console.log(result)
于 2019-05-26T14:47:25.653 回答