繁体   English   中英

以下JavaScript reduce函数的模式是什么?

[英]What's the pattern of the following JavaScript reduce function?

我在理解以下缩减功能时遇到了麻烦:

function findDeep(arr, obj) {
  return arr.map(item => {
    if (item.name === obj.name) {
      return arr
    } else if (item.children) {
      return findDeep(item.children, obj)
    } else {
      return undefined
    }
  }).reduce((prev, curr) => {
    console.log('prev: ', prev)
    console.log('curr: ', curr)
    return prev || curr
  })
}

应用于此对象:

const mockApps = {
  name: 'orange',
  children: [{
    name: 'white'
  }, {
    name: 'green',
    children: [{
      name: 'yellow',
      children: [{
        name: 'red'
      }, {
        name: 'white'
      }]
    }, {
      name: 'green',
      children: [{
        name: 'purple'
      }]
    }]
  }, {
    name: 'gray'
  }]
}

const activeApp = {
  name: 'purple',
  color: 'purple',
  path: 'writer'
}

findDeep(mockApps.children, activeApp)

我认为该模式将类似于MDN的示例:

[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, currentIndex, array) {
  return previousValue + currentValue;
});

在此处输入图片说明

但是令我惊讶的是,我理论上的理解与输出有所不同:

在此处输入图片说明

我以为previousValue将是前一次迭代的returnValue ,但是正如您在控制台中看到的那样,即使前一个迭代的currentValue不是,第三个prev也是未定义的。

reduce函数的正确模式是什么?

这是CodePen

看来您假设控制台输出属于reduce一轮运行,但这不是事实。

函数findDeep递归地调用自身,因此您将获得来自reduce不同调用的输出。

我建议您如下修改代码,以便在调用并退出findDeep时也可以在控制台中看到它:

function findDeep(arr, obj) {
  console.log('Entering findDeep');
  var res = arr.map(item => {
    if (item.name === obj.name) {
      return arr
    } else if (item.children) {
      return findDeep(item.children, obj)
    } else {
      return undefined
    }
  }).reduce((prev, curr) => {
    console.log('prev: ' + JSON.stringify(prev));
    console.log('curr: ' + JSON.stringify(curr));
    console.log('return: ' + JSON.stringify(prev || curr));
    return prev || curr;
  });
  console.log('Exiting from findDeep');
  return res;
}

这应该可以弄清这个问题。 以下是将日志写入浏览器的代码段:

 console = { log: function(msg) { document.write(msg + '<br>'); }} function findDeep(arr, obj) { console.log('Entering findDeep'); var res = arr.map(item => { if (item.name === obj.name) { return arr } else if (item.children) { return findDeep(item.children, obj) } else { return undefined } }).reduce((prev, curr) => { console.log('prev: ' + JSON.stringify(prev)); console.log('curr: ' + JSON.stringify(curr)); console.log('return: ' + JSON.stringify(prev || curr)); return prev || curr; }); console.log('Exiting from findDeep'); return res; } const mockApps = { name: 'orange', children: [{ name: 'white' }, { name: 'green', children: [{ name: 'yellow', children: [{ name: 'red' }, { name: 'white' }] }, { name: 'green', children: [{ name: 'purple' }] }] }, { name: 'gray' }] } const activeApp = { name: 'purple', color: 'purple', path: 'writer' } findDeep(mockApps.children, activeApp) 

如您所见,在以前看来prev的值与上次迭代的返回值不对应的地方,现在很清楚这两个迭代属于reduce的不同调用,因此它的作用与您期望的一样。

如果您遵循该代码,则传递给map (级别0)的第一个值是:

{name: 'white'}

它没有紫色或任何子项的名称,因此结果数组现在为:

[undefined]

下一项是:

{name: 'green',
 children: [{
   name: 'yellow',
   children: [{
     name: 'red'
     }, {
     name: 'white'
     }]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]
   }]
}

它具有属性,因此其值将传递给findDeep (级别1)的递归调用,该调用为:

 [{
   name: 'yellow',
   children: [{
     name: 'red'
     }, {
     name: 'white'
     }]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]
 }]

传递给map的第一项,然后再次递归调用findDeep (级别2):

   [{name: 'red'},
    {name: 'white'}]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]

第一项没有紫色或子级名称 ,因此此级别映射数组为:

[undefined]

下一项相同,所以现在是:

[undefined, undefined]

下一个名称为“ purple”,因此将其添加到数组中:

[undefined, undefined,{name:'purple'}]

那是通过reduce进行的 ,它没有累加器就被调用,因此前两个值作为prevcur传递。 由于prev为false,因此curr的值作为累加器返回,因此在下一次调用时,这些值是undefined{name:'purple'} ,因此返回到1级映射 ,其数组现在为:

[{name:'purple'}]

此级别没有更多成员,因此将其减少。 由于它是数组中的唯一成员,并且没有传入任何累加器,因此只返回了它,因此级别1的结果为:

[{name:'purple'}]

级别0的最后一个成员也返回undefined,因此最终级别0的数组为:

[{name:'purple'}, undefined]

通过传递来减少,两个值分别是prevcurr 由于上一个对象不是falsey,它回来了,最后的结果是:

[{name:'purple'}]

请注意,如果使用JSON.stringify查看对象和数组,则undefined更改为“ null”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM