什么';下面JavaScript reduce函数的模式是什么?

什么';下面JavaScript reduce函数的模式是什么?,javascript,mapreduce,Javascript,Mapreduce,我无法理解以下reduce函数: 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 } }).r

我无法理解以下reduce函数:

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)
我认为模式将类似于以下示例:

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

我原以为
previousValue
将是上一次迭代的
returnValue
,但正如您在控制台中看到的,第三次
prev
未定义,即使上一次迭代的
currentValue
未定义

reduce
功能的正确模式是什么


以下是。

您似乎假设控制台输出属于一次运行的
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){
编写(msg+“
”); }} 功能findDeep(arr、obj){ console.log('进入findDeep'); var res=arr.map(项目=>{ if(item.name==对象名){ 返回arr }else if(项。子项){ 返回findDeep(item.children,obj) }否则{ 返回未定义 } }).减少((上一个,当前)=>{ log('prev:'+JSON.stringify(prev)); log('curr:'+JSON.stringify(curr)); log('return:'+JSON.stringify(prev | | curr)); 返回上一个| | curr; }); log('从findDeep退出'); 返回res; } 常量mockApps={ 名称:“橙色”, 儿童:[{ 姓名:“白色” }, { 名称:'绿色', 儿童:[{ 名称:“黄色”, 儿童:[{ 姓名:“红色” }, { 姓名:“白色” }] }, { 名称:'绿色', 儿童:[{ 名字:“紫色” }] }] }, { 姓名:“格雷” }] } 常量activeApp={ 名称:“紫色”, 颜色:'紫色', 路径:“作者” }
findDeep(mockApps.children,activeApp)
您似乎假设控制台输出属于一次运行的
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){
编写(msg+“
”); }} 功能findDeep(arr、obj){ console.log('进入findDeep'); var res=arr.map(项目=>{ if(item.name==对象名){ 返回arr }else if(项。子项){ 返回findDeep(item.children,obj) }否则{ 返回未定义 } }).减少((上一个,当前)=>{ log('prev:'+JSON.stringify(prev)); log('curr:'+JSON.stringify(curr)); log('return:'+JSON.stringify(prev | | curr)); 返回上一个| | curr; }); log('从findDeep退出'); 返回res; } 常量mockApps={ 名称:“橙色”, 儿童:[{ 姓名:“白色” }, { 名称:'绿色', 儿童:[{ 名称:“黄色”, 儿童:[{ 姓名:“红色” }, { 姓名:“白色” }] }, { 名称:'绿色', 儿童:[{ 名字:“紫色” }] }] }, { 姓名:“格雷” }] } 常量activeApp={ 名称:“紫色”, 颜色:'紫色', 路径:“作者” }
findDeep(mockApps.children,activeApp)
如果按照代码进行操作,则传递到map(级别0)的第一个值是:

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

[undefined]
[undefined]
[{name:'purple'}]
下一项是:

{name: 'green',
 children: [{
   name: 'yellow',
   children: [{
     name: 'red'
     }, {
     name: 'white'
     }]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]
   }]
}
它有一个children属性,因此它的值被传递给对findDeep的递归调用(级别1),即:

 [{
   name: 'yellow',
   children: [{
     name: 'red'
     }, {
     name: 'white'
     }]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]
 }]
传递给map的第一个项,再次递归调用findDeep(第2级),使用:

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

[undefined]
[undefined]
[{name:'purple'}]
下一项也一样,所以现在是:

[undefined, undefined]
下一个名称为“紫色”,因此将其添加到数组中:

[undefined, undefined,{name:'purple'}]
这是通过reduce运行的,reduce调用时没有累加器,因此前两个值作为prev和cur传递。由于prev为false,curr的值作为累加器返回,因此在下一次调用中,值未定义且
{name:'purple'}
,因此返回到级别1映射,其数组现在为:

[undefined]
[undefined]
[{name:'purple'}]
此级别中没有更多成员,因此将传递给reduced。由于它是数组中唯一的成员,并且没有传入累加器,因此只返回它,因此级别1的结果是:

[{name:'purple'}]
[{name:'purple'}]
级别0的最后一个成员也返回undefined,因此最终的级别0数组是:

[{name:'purple'}, undefined]
它被传递到reduce,两个值分别为prev和curr。由于prev对象不是false,因此返回该对象,最终结果为:

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

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

如果按照代码进行操作,则传递给map(级别0)的第一个值是:

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

[undefined]
[undefined]
[{name:'purple'}]
下一项是:

{name: 'green',
 children: [{
   name: 'yellow',
   children: [{
     name: 'red'
     }, {
     name: 'white'
     }]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]
   }]
}
它有一个children属性,因此它的值被传递给对findDeep的递归调用(级别1),即:

 [{
   name: 'yellow',
   children: [{
     name: 'red'
     }, {
     name: 'white'
     }]
   }, {
     name: 'green',
     children: [{
       name: 'purple'
     }]
 }]
传递给map的第一个项,再次递归调用findDeep(第2级),使用:

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

[undefined]
[undefined]
[{name:'purple'}]
下一项也一样,所以现在是:

[undefined, undefined]
下一个名称为“紫色”,因此将其添加到数组中:

[undefined, undefined,{name:'purple'}]
这是通过reduce运行的,reduce调用时没有累加器,因此前两个值作为prev和cur传递。因为prev是fal