【问题标题】:Understanding Javascript Shorthand Arrow Syntax Alongside Array find()了解数组 find() 旁边的 Javascript 速记箭头语法
【发布时间】:2019-03-15 19:40:28
【问题描述】:

如果可以的话,尽量不要接触我的新手,我只是想准确了解这个函数中发生了什么,以便我可以更好地根据我的用例对其进行调整,并在需要时编写更简洁/更短的代码。该功能当然可以使用,我可以使用它,但是当我不完全理解我正在使用的代码时,它会困扰我。我想我大部分都理解,但我很难把所有的部分放在一起。如果这是重复的,那么所有的道歉,请这样标记,但我找不到我想要理解的确切答案。从其他已回答的问题和外部文章中,我已经能够了解发生的大部分情况,但我仍然卡在几个点上。

具体代码是:

const userBy = id => u => u.id == id; 
const users = [{ id: 1, name: "Kaio" }, { id: 2, name: "Gabriella" }, { id: 3, name: "Enzo" }];
const id = 2;
const user = users.find(userBy(id));

我的主要问题围绕着:

const userBy = id => u => u.id == id;

我从这篇文章中得到了代码,以防万一需要更多上下文,尽管前面提到的代码应该足够了 - https://medium.com/@kaiosilveira/mastering-javascript-arrays-beyond-for-and-foreach-loops-e2ecf9dfe3e

我知道在“userBy”函数中,“id”作为参数传入。我也明白,在简写语法中,return 语句是隐含的,并且 find() 方法有它自己的三个参数(元素、索引、数组),很像我理解和经常使用的 forEach() 函数。

总而言之 - 我知道“id”作为参数传入,但是如果我理解正确,“u”将被返回和/或作为最终函数的参数传入,其中'u' 的指定属性 'id' 等于传递给原始函数的参数 'id'。而且由于我知道 find() 方法正在遍历一个数组,我可以合理地推断出 'u' 是该数组的当前元素/索引。

我很难理解的具体部分是 'u' 如何将元素/索引捕获为它的值。还有为什么 'u' 需要在它自己的函数中,而不是作为启动函数的 'id' 参数旁边的另一个参数。

就像我说的那样,无论我是否理解,该功能都可以正常工作并且一切正常。但我将非常感谢任何能花时间向我解释到底发生了什么的人。我已经自己研究并理解了所有内容,只需要一点点掌握我提到的最后几点。

[发布回答编辑] 它要求我解释为什么这个问题与 What do multiple arrow functions mean in javascript? 不同。它们非常相似,但我认为根据我的具体情况添加 Array.prototype.find 方法足以区分它以保证它自己的解释。在它的核心,虽然我可以看到有些人可能会将它标记为相同,所以如果其他人有这种感觉,那么一定要把它标记为重复。对社区最好的事情对我来说都很好,我很感激社区花时间帮助我理解我的问题。

【问题讨论】:

  • 我无法为您提供答案,但请从函数式编程中查看这个想法:stackoverflow.com/questions/36314/what-is-currying
  • 这是一个柯里化函数。 userBy(id) 返回一个用作find 的回调函数:What do multiple arrow functions mean in javascript?
  • 所以重写没有粗箭头:const userBy = function(id) { return function (u) { return u.id == id } } 所以第一次调用是设置 id 并返回函数。那么当 find 执行时,它会将u 传递给函数。
  • u[].find() 传递给输出函数id 通过闭包被记忆为你在调用包装器时设置的任何值。
  • 感谢 Matt 和 adiga 指出柯里化,感谢信息。还要感谢其他所有人,就像其他答案一样,您帮助我意识到了我所缺少的观点。非常感谢大家。

标签: javascript ecmascript-6 arrow-functions


【解决方案1】:

首先,让我们看看 .find 在做什么。 .find 的实现如下所示:

Array.prototype.find = function (callback) {
  for (let i = 0; i < this.length; i++) {
    const match = callback(this[i], i, this);
    if (match) {
      return this[i];
    }
  }
}

Find 期望您向它传递一个函数,并且该函数将被重复调用,一次传递一个数组的每个元素(加上索引和数组),直到其中一个通过测试。所以正常使用这个是这样的,找到 id 为 2 的用户:

users.find((user) => {
  if (user.id === 2) {
    return true;
  }
  return false;
});

或更短:

users.find(user => user.id === 2);

现在您显示的代码更进一步。它预见到了想要找到user.id === 2,还有user.id === 1,和user.id === 18273等的可能性。所以他们创建了一个名为userBy的辅助函数,它可以产生其他函数。换句话说,这段代码:

const userBy = id => u => u.id == id; 

... 是一个生产看起来像 user =&gt; user.id === 2 的函数的工厂,除了它可以创建的函数不仅可以与 2 进行比较,还可以创建任何你想要的 id。

因此,有了这个,一行代码如下所示:

const user = users.find(userBy(2));

...基本上意味着“创建函数user =&gt; user.id === 2,然后将其传递给users.find

【讨论】:

  • 更加澄清,非常感谢,因为它的解释更加精确。与其他答案一样,我非常感谢您抽出时间来回答。
【解决方案2】:

这是因为 userBy 函数实际上并没有遍历数组 - Array.find 接受一个具有布尔返回值的函数,因此执行实际查找的函数是匿名子函数 u =&gt; u.id == id。这是它在 ES5 中的样子:

var userBy = function(id) {
    return function(u) {
        u.id == id;
    };
};

这里,userBy 函数返回一个回调/测试函数,这在Array.find 中使用。如果您不必将 id 作为参数传递,您可以像这样简化它,只使用内部函数:

const userBy = u => u.id == id;
const user = users.find(userBy);

【讨论】:

  • 谢谢你,这很好地清除了它。我完全错过了'userBy'将函数传递给find()方法并且正在进行实际迭代的观点。感谢您对理解的帮助,非常感谢。
  • 没问题@z4nta0,如果我的回答解决了您的问题,请点击我的回答左侧的灰色勾号将其标记为已接受。
  • 我只能选择 1 个“接受”的答案,而我选择 Nicholas 的答案只是因为它解释得更详细。不过,我很感谢您抽出宝贵的时间,无论如何,您的回答确实帮助我理解了。
猜你喜欢
  • 1970-01-01
  • 2017-03-05
  • 2023-02-22
  • 1970-01-01
  • 2019-05-23
  • 2015-01-18
  • 2012-08-27
  • 2020-09-09
  • 1970-01-01
相关资源
最近更新 更多