reduce解决读取多层嵌套对象属性

        在使用reduce时突然发现reduce似乎可以遍历对象嵌套结构

function getObjectPropertyValue(obj, propertyPath) {
  return propertyPath.split('.').reduce((result, key) => result[key], obj);
}

const person = {
  name: 'John',
  address: {
    city: 'New York',
    street: '123 ABC Street'
  }
};

const name = getObjectPropertyValue(person, 'name');
console.log(name); // John

const city = getObjectPropertyValue(person, 'address.city');
console.log(city); // New York

const street = getObjectPropertyValue(person, 'address.street');
console.log(street); // 123 ABC Street

        查询文档:Array methods

reduce/reduceRight

When we need to iterate over an array – we can use forEachfor or for..of.

When we need to iterate and return the data for each element – we can use map.

The methods arr.reduce and arr.reduceRight also belong to that breed, but are a little bit more intricate. They are used to calculate a single value based on the array.

The syntax is:

let value = arr.reduce(function(accumulator, item, index, array) {
  // ...
}, [initial]);

The function is applied to all array elements one after another and “carries on” its result to the next call.

Arguments:

  • accumulator – is the result of the previous function call, equals initial the first time (if initial is provided).
  • item – is the current array item.
  • index – is its position.
  • array – is the array.

As function is applied, the result of the previous function call is passed to the next one as the first argument.

So, the first argument is essentially the accumulator that stores the combined result of all previous executions. And at the end it becomes the result of reduce.

Sounds complicated?

The easiest way to grasp that is by example.

Here we get a sum of an array in one line:

let arr = [1, 2, 3, 4, 5];

let result = arr.reduce((sum, current) => sum + current, 0);

alert(result); // 15

The function passed to reduce uses only 2 arguments, that’s typically enough.

Let’s see the details of what’s going on.

  1. On the first run, sum is the initial value (the last argument of reduce), equals 0, and current is the first array element, equals 1. So the function result is 1.
  2. On the second run, sum = 1, we add the second array element (2) to it and return.
  3. On the 3rd run, sum = 3 and we add one more element to it, and so on…

The calculation flow:

Or in the form of a table, where each row represents a function call on the next array element:

sum current result
the first call 0 1 1
the second call 1 2 3
the third call 3 3 6
the fourth call 6 4 10
the fifth call 10 5 15

Here we can clearly see how the result of the previous call becomes the first argument of the next one.

We also can omit the initial value:

let arr = [1, 2, 3, 4, 5];

// removed initial value from reduce (no 0)
let result = arr.reduce((sum, current) => sum + current);

alert( result ); // 15

The result is the same. That’s because if there’s no initial, then reduce takes the first element of the array as the initial value and starts the iteration from the 2nd element.

The calculation table is the same as above, minus the first row.

But such use requires an extreme care. If the array is empty, then reduce call without initial value gives an error.

Here’s an example:

let arr = [];

// Error: Reduce of empty array with no initial value
// if the initial value existed, reduce would return it for the empty arr.
arr.reduce((sum, current) => sum + current);

So it’s advised to always specify the initial value.

The method arr.reduceRight does the same, but goes from right to left.

        可以看出官方推荐的用法是使用这个累加器可以方便的计算一个数组元素的和,通过 return 可以把每次迭代的值返回给total作为下一次的初始值,如果我们 return 一个对象的话,不就可以依次读取多层嵌套的对象的属性了吗? 

        我们将子级结构作为上一次的值返回,从而实现遍历多层嵌套结构。在reduce函数的回调函数中,根据需要选择将子级结构与累积值(上一次的值)进行合并或者进行其他操作,并将结果作为下一次迭代的累积值返回。

        另外reduce还可以实现数据转换与映射,使用 reduce 函数将一个数据集转换为另一种格式的数据集:

const people = [
  { name: 'John', age: 25 },
  { name: 'Jane', age: 30 },
  { name: 'Mike', age: 35 }
];
const nameAgeMap = people.reduce((acc, curr) => {
  acc[curr.name] = curr.age;
  return acc;
}, {});
console.log(nameAgeMap); // { John: 25, Jane: 30, Mike: 35 }

你可能感兴趣的:(前端,前端,javascript,数据结构,ecmascript,es6)