如何理解JavaScript中的这段代码片段 [英] How to understand this fragment of code in javascript react

查看:83
本文介绍了如何理解JavaScript中的这段代码片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Internet上的js中发现了该函数的实现,该函数递归地过滤了一个对象数组,每个对象都可能具有属性"children"(即对象数组),并且该对象也可能具有子对象,依此类推.该功能正常工作,但我对此不太了解.

I found the implementation of the function in js in the Internet, This function recursively filters an array of objects, each object may have property "children" which is array of objects and that objects also may have children and so on. The function works correctly but I didn't understand it a bit.

这是我的功能:

getFilteredArray (array, key, searchString) {
    const res = array.filter(function iter(o) {

      if (o[key].toLowerCase().includes(searchString.toLowerCase())) {
        return true;
      }

      if(o.children){
        return (o.children = o.children.filter(iter)).length;
      }
    });

    this.setState({
      filteredArray: res
    });
  }

我在这段代码中看不懂:

I don't understand in this code:

if(o.children){
        return (o.children = o.children.filter(iter)).length;
      }  

我们可以简化表达式(o.children = o.children.filter(iter)).length;吗?

Can we simplify this expression (o.children = o.children.filter(iter)).length; ?

为什么我们返回数组的长度而不是数组本身?

Why we return the length of array not the array itself?

并且函数"iter"接受一个作为对象的参数.为什么我们只写o.children.filter(iter)而没有任何参数传递给"iter"呢?根据递归教程,如果函数需要它们,则总是传递参数.但是在这里我们没有通过,这很奇怪.

And function "iter" accepts one argument that is object. Why we just write o.children.filter(iter) without any arguments passed to the "iter" here? according to recursion tutorials, there are arguments always passed, if the function requires them. But here we don't pass, this is strangely.

推荐答案

这是一个重新编写,它力求清晰,并简化了逻辑以消除干扰:

Here's a re-write that strives for clarity and simplifies the logic a bit to remove distractions:

const recursivelyFilter = (arr, key, searchString) => {
  return arr.filter(function iter(obj) {
    if (obj[key].includes(searchString)) {
      return true;
    }

    if (obj.children) {
      obj.children = obj.children.filter(child => iter(child));
      return obj.children.length > 0;
    }

    return false;
  });
};

Array#filter 是此代码的内容. filter接受一个回调,该回调应返回一个布尔值以确定元素是否将包含在结果数组中. 就地.

Array#filter is the meat of this code. filter accepts a callback which should return a boolean to determine whether an element will be included in the result array. It doesn't work in-place.

基本案例(递归的终止条件)为:

The base cases (terminating conditions for the recursion) are:

  • 如果当前对象(
  • If the current object (a node in the tree) has a key key matching searchTerm, return true.
  • If the current node doesn't match searchTerm and has no children, return false. In the original code, returning undefined defaults to falsey.

递归的情况是:

  • 如果当前节点有子节点,则使用iter函数的布尔结果来递归过滤它们.如果当前节点的至少一个后代通过了过滤条件,则将当前节点包括在其父节点的children数组中,否则将其删除.该代码将新的子数组的长度作为布尔值来实现.
  • If the current node has children, recursively filter them using the boolean result of the iter function. If at least one descendant of the current node passes the filter condition, include the current node in its parent's children array, otherwise remove it. The code treats the length of the new child array as a boolean to achieve this.

return (o.children = o.children.filter(iter)).length;首先执行对o.children的赋值,这是必需的,因为o.children.filter返回数组的新副本.分配完成后,表达式将解析为新的o.children并返回其length属性.然后根据上述递归情况规则,将该长度视为真/假.总计:

return (o.children = o.children.filter(iter)).length; first performs an assignment to o.children, necessary because o.children.filter returns a fresh copy of the array. After the assignment is finished, the expression resolves to the new o.children and its length property is returned. The length is then treated as truthy/falsey according to the recursive case rule described above. This amounts to:

obj.children = obj.children.filter(child => iter(child));
return obj.children.length > 0;

如果我们返回数组本身,则所有内容都将被视为true,因为空数组[]的计算结果为true.另一方面,[].length评估为假,这是期望的结果.

If we returned the array itself, everything would be treated as true because an empty array, [], evaluates to true. [].length, on the other hand, evaluates to false, which is the desired outcome.

对于o.children.filter(iter)Array#filter接受回调作为其第一个参数,该参数可以是诸如iter之类的函数变量.另一种选择是直接在参数列表中创建一个匿名函数.这通常是这样做的.上面的版本添加了一个箭头包装器,但这显然是不必要的额外间接层,因为lone参数只是通过包装器传递.我们也可以在这里使用function关键字.无论如何,目标是相同的,那就是我们将函数传递到filter中以调用每个元素.

As for o.children.filter(iter), Array#filter accepts a callback as its first parameter, which can be a function variable such as iter. Another option is creating an anonymous function directly in the argument list; this is usually how it's done. The above version adds an arrow wrapper, but it's an obviously unnecessary extra layer of indirection since the lone parameter is just passed through the wrapper. We could also use the function keyword here; whatever the case, the goal is the same, which is that we pass a function into filter to call on each element.

顺便说一句,该函数假定在array中嵌套对象的所有节点上都设置了key,并且定义了obj[key].includes.显然,作者脑海中有一个非常具体的数据结构和目的,对过早地归纳不感兴趣.

By the way, the function assumes that key is set on all the nodes of the nested objects in array and that obj[key].includes is defined. Clearly, the author had a very specific data structure and purpose in mind and wasn't interested in prematurely generalizing.

以下是说明其操作的测试代码.玩弄它应该有助于您的理解.

Here's test code illustrating its operation. Playing around with it should help your understanding.

const recursivelyFilter = (arr, key, searchString) => {
  return arr.filter(function iter(obj) {
    if (obj[key].includes(searchString)) {
      return true;
    }

    if (obj.children) {
      obj.children = obj.children.filter(child => iter(child));
      return obj.children.length > 0;
    }

    return false;
  });
};

const arr = [
  {
    foo: "bar", 
    children: [
      {
        foo: "baz", 
        children: [
          {foo: "quux"},
          {foo: "quuz"},          
        ]
      }
    ]
  },
  {
    foo: "corge", 
    children: [
      {foo: "quux"}
    ]
  },
  {
    foo: "grault",
    children: [{foo: "bar"}]
  }
];

console.log(recursivelyFilter(arr, "foo", "quux"));

这篇关于如何理解JavaScript中的这段代码片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆