Поскольку я изучил Array.reduce() , я не могу жить без него.

JavaScript

Из всех методов массива после ES6 мне труднее всего понятьArray.reduce().

На первый взгляд это кажется простым и неинтересным методом, который мало что дает. Но под неприметным видом,Array.reduce()На самом деле мощное и гибкое дополнение к набору инструментов разработчика.

Сегодня мы будем изучать черезArray.reduce()Некоторые интересные вещи, которые можно сделать.

принцип

Большинство современных методов массива возвращают новый массив, иArray.reduce()более гибкий. Он может возвращать любое значение, и его функция заключается в объединении содержимого массива в одно значение.

Это значение может быть числом, строкой или даже объектом или новым массивом. Это та часть, которая постоянно спотыкается, я не ожидал, что она будет такой гибкой!

использование

Array.reduce()Принимает два параметра: метод обратного вызова для каждого элемента массива и начальное значение.

Этот обратный вызов получает 4 параметра, первые два параметра:accumulatorтекущее совокупное значение,currentявляется текущим элементом, когда массив зацикливается. Какое бы значение вы ни вернули, оно будет передано следующему элементу цикла в качестве аккумулятора. Начальное значение будет использоваться как аккумулятор для первого цикла.


var myNewArray = [].reduce(function (accumulator, current) {
  return accumulator;
}, starting);

Рассмотрим несколько практических примеров.

1. Суммирование массива

Предположим, вы хотите сложить набор чисел. использоватьArray.forEach()Наверное сделать так:


var total = 0;

[1, 2, 3].forEach(function (num) {
  total += num;
});

ЭтоArray.reduce()Самый используемый пример. Я нашел слово «аккумулятор» сбивающим с толку, поэтому в примере я заменил его наsum, ибо в этом смысл поиска примирения.


var total = [1, 2, 3].reduce(function (sum, current) {
  return sum + current;
}, 0);

входящий сюда0как начальное значение.

В обратном вызове добавьте текущее значение кsum, его значение является начальным значением в первом раунде цикла0, который затем становится1(Первоначальный значение0плюс текущее значение элемента1), затем становится3(накопленное значение1плюс текущее значение элемента2), и так далее

2. Комбинируйте несколько методов массива

Предположим, естьwizardsмножество:


var wizards = [
  {
    name: 'Harry Potter',
    house: 'Gryfindor'
  },
  {
    name: 'Cedric Diggory',
    house: 'Hufflepuff'
  },
  {
    name: 'Tonks',
    house: 'Hufflepuff'
  },
  {
    name: 'Ronald Weasley',
    house: 'Gryfindor'
  },
  {
    name: 'Hermione Granger',
    house: 'Gryfindor'
  }
];

Вы хотите создать новый массив, содержащий только имена волшебников, живущих в Хаффлпаффе. Возможный способ - использоватьArray.filter()способ получитьhouseсобственностьHufflepuffиз wizards. затем используйтеArray.map()метод создаетnameНовый массив свойств.


var hufflepuff = wizards.filter(function (wizard) {
  return wizard.house === 'Hufflepuff';
}).map(function (wizard) {
  return wizard.name;
});

использоватьArray.reduce()метод, мы можем получить тот же результат за один шаг, с улучшенной производительностью. передать пустой массив[]как начальное значение. Судя по каждой петлеwizard.houseЭтоHufflepuff. Если да, добавьте вnewArrв (т.е.accumulator), иначе ничего не делать.

Независимо от того, верно ли условие суждения или нет, в конце оно вернетсяnewArrкак следующий циклaccumulator.


var hufflepuff = wizards.reduce(function (newArr, wizard) {
  if (wizard.house === 'Hufflepuff') {
    newArr.push(wizard.name);
  }
  return newArr;
}, []);

3. Сгенерируйте теги HTML из массива

Так что, если вы хотите создать неупорядоченный список волшебников, живущих в Хаффлпаффе? Не в этот разArray.reduce()Передайте пустой массив в качестве начального значения, но массив с именемhtmlпустая строка''.

еслиwizard.houseравноHufflepuff, мы будемwizard.nameс элементами спискаliзавернуть и склеитьhtmlв строке. затем вернутьсяhtmlкак следующий циклaccumulator.


var hufflepuffList = wizards.reduce(function (html, wizard) {
  if (wizard.house === 'Hufflepuff') {
    html += '<li>' + wizard.name + '</li>';
  }
  return html;
}, '');

существуетArray.reduce()Добавьте начальный и конечный теги неупорядоченного списка до и после, и вы сможете вставить его в DOM.


var hufflepuffList = '<ul>' + wizards.reduce(function (html, wizard) {
  if (wizard.house === 'Hufflepuff') {
    html += '<li>' + wizard.name + '</li>';
  }
  return html;
}, '') + '</ul>';

4. Группировка элементов массива

Лодаш имеетgroupBy()метод группировки элементов массива по определенному критерию.

Предположим, у вас есть массив чисел.

если хочешь поставитьnumbersЭлементы в массиве группируются по значению целочисленной части, что можно сделать с помощью lodash:


var numbers = [6.1, 4.2, 6.3];

// 返回 {'4': [4.2], '6': [6.1, 6.3]}
_.groupBy(numbers, Math.floor);

Если у вас есть массив слов, вы хотитеwordsЧтобы сгруппировать по длине слова в , вы можете сделать это:


var words = ['one', 'two', 'three'];

// 返回 {'3': ['one', 'two'], '5': ['three']}
_.groupBy(words, 'length');

использовать Array.reduce()выполнить groupBy()функция

ты можешь использовать этоArray.reduce()способ достижения той же функции.

Создадим функцию полезностиgroupBy(), который принимает массив и критерии группировки в качестве аргументов. существуетgroupBy()Внутренне выполняется в массивеArray.reduce(), передать пустой объект{}в качестве начального значения, а затем вернуть результат.


var groupBy = function (arr, criteria) {
  return arr.reduce(function (obj, item) {
    // 省略代码
  }, {});
};

существует Array.reduce()Внутри функции обратного вызова мы будем судитьcriteriaЭто функция илиitemхарактеристики. затем получить текущийitemзначение .

еслиobjЕсли свойство еще не существует в , создайте его и назначьте ему пустой массив. Наконец, будетitem добавить в keyв массиве, а затем вернуть объект как следующий циклaccumulator.


var groupBy = function (arr, criteria) {
  return arr.reduce(function (obj, item) {

    // 判断criteria是函数还是属性名
    var key = typeof criteria === 'function' ? criteria(item) : item[criteria];

    // 如果属性不存在,则创建一个
    if (!obj.hasOwnProperty(key)) {
      obj[key] = [];
    }

    // 将元素加入数组
    obj[key].push(item);

    // 返回这个对象
    return obj;

  }, {});
};

5. Объедините данные в единый массив

помнить предыдущийwizardsмножество?


var wizards = [
  {
    name: 'Harry Potter',
    house: 'Gryfindor'
  },
  {
    name: 'Cedric Diggory',
    house: 'Hufflepuff'
  },
  {
    name: 'Tonks',
    house: 'Hufflepuff'
  },
  {
    name: 'Ronald Weasley',
    house: 'Gryfindor'
  },
  {
    name: 'Hermione Granger',
    house: 'Gryfindor'
  }
];

Если есть другая часть данных, очки, заработанные каждым мастером, составляют:


var points = {
  HarryPotter: 500,
  CedricDiggory: 750,
  RonaldWeasley: 100,
  HermioneGranger: 1270
};

Предположим, вы хотите объединить две части данных в массив, то есть поместитьpointsК каждому объекту мастера добавляется числовое значение. Что вы будете делать?

Array.reduce()Метод особенно подходит!


var wizardsWithPoints = wizards.reduce(function (arr, wizard) {

  // 移除巫师名字中的空格,用来获取对应的 points
  var key = wizard.name.replace(' ', '');

  // 如果wizard有points,则加上它,否则设置为0
  if (points[key]) {
    wizard.points = points[key];
  } else {
    wizard.points = 0;
  }

  // 把wizard对象加入到新数组里
  arr.push(wizard);

  // 返回这个数组
  return arr;

}, []);

На самом деле здесьArray.mapЭто также очень удобно в реализации.

6. Объедините данные в один объект

Что делать, если вы хотите объединить данные из двух источников в один объект, то есть имя мастера в качестве имени свойства, а дом и точки в качестве значений свойства? Так же,Array.reduce()очень подходит.


var wizardsAsAnObject = wizards.reduce(function (obj, wizard) {

  // 移除巫师名字中的空格,用来获取对应的 points
  var key = wizard.name.replace(' ', '');

  // 如果wizard有points,则加上它,否则设置为0
  if (points[key]) {
    wizard.points = points[key];
  } else {
    wizard.points = 0;
  }

  // 删除 name 属性
  delete wizard.name;

  // 把 wizard 数据添加到新对象中
  obj[key] = wizard;

  // 返回该对象
  return obj;

}, {});

Суммировать: Array.reduce()действительно ароматный

Array.reduce()Методы превратились из того, что я когда-то считал непригодным для использования, в мой любимый метод JavaScript. Итак, вы должны использовать его? Когда это будет доступно?

Array.reduce()метод имеет хорошую поддержку браузера. Поддерживаются все современные браузеры, включая IE9 и выше. Мобильные браузеры также давно поддерживаются. Если вам также необходимо поддерживать старые браузеры, вы можете добавить полифилл для поддержкиIE6.

Array.reduce()Самым большим недостатком может быть то, что это немного сбивает с толку людей, которые никогда не контактировали с ним. использовать в сочетанииArray.filter() иArray.map()Он выполняется медленнее и содержит избыточные шаги, но его легче читать, и из названия метода очевидно, что он делает.

Тем не менее иногдаArray.reduce()Это также может сделать сложные вещи более простыми. groupBy()Вспомогательные функции являются хорошим примером.

В конце концов, это должен быть еще один инструмент в вашем наборе инструментов, невероятно мощный при правильном использовании.

оригинал:24ways.org/2019/five-i…
Переведено и аранжировано переводческой станцией 1024.

есть небольшая просьба

Я написал в Наггетс более 20 технических статей, благодаря всеобщей любви есть несколько статей, которые были прочитаны более 10 000, а общее количество прочтений перевалило за 100 000. Большое спасибо за ваши золотые пальцы здесь! Но есть и небольшое сожаление: после каждой статьи я оставляю свой QR-код станции перевода в паблике WeChat 1024, но не знаю, почему мало кто обращает на это внимание. Если бы 10% читателей обращали внимание на каждую статью, наверное, я бы просыпался со смеху во сне, ха-ха... Это как моя детская мечта "Если бы вся страна дала мне один доллар, у меня были бы сотни миллионов! «Было, можно только сказать, чтоЧудо. Теперь у меня есть эта безумная идея, и я хочу пригласить вас создать ее вместе.Чудо! Пока вы двигаете своим золотым пальцем и следите за официальной учетной записью 1024 Translation Station, вы можете как можно скорее получить техническую галантерею, которую я создал с душой! Не тратьте ни копейки! WeChat также недавно запустил функцию платного чтения, что указывает на то, что взимание платы за высококачественный контент является основной тенденцией, и в будущем будет все меньше и меньше бесплатного высококачественного контента! Я также создал фан-группу в WeChat, если случится чудо, я обязательно вернусь! Ниже приведен QR-код, отсканируйте его мобильным телефоном и станьте свидетелем чуда вместе!

微信公众号:1024译站