Сводные значения, полученные из функции обратного вызова в ES6? - PullRequest
0 голосов
/ 03 июня 2019

У меня есть класс, который предоставляет способ перечисления некоторых значений (которые могут быть неправильно сохранены в массиве или другой встроенной коллекции):

class DataStore {
  constructor(values) {
    this.values = values;
  }
  forEachData(callback) {
    // the callback is invoked with items specific to the logic of DataStore
    callback(0);
    callback(1);
    for (const x of this.values) {
      callback(x);
    }
    for (const x of this.values) {
      callback(2 * x);
    }
  }
}

В другой функции, которая использует этот класс, я хотел бы выполнить некоторую операцию агрегации (то есть сокращения) для значений, возвращаемых обратным вызовом. Есть ли краткий способ выразить это с помощью Array.prototype.reduce () или каким-либо другим встроенным способом без выполнения сокращения вручную?

// Inside my function
const data_store = ...; // DataStore object
const aggregate_op = (accumulator, current_value) => Math.min(accumulator, f(current_value));

// I'm wondering if there is a built-in language or library feature that does this kind of reduction:
let answer = 0;
data_store.forEachData(x => {
  answer = aggregate_op(answer, x);
});

Примечание. Сокращение вручную достаточно просто, как описано выше, но, возможно, сокращение массива также очень просто без использования Array.prototype.reduce ():

const arr = [1, 3, 5, 7, 9];
let answer = 0;
arr.forEach(x => {
  answer = aggregate_op(answer, x);
});

1 Ответ

0 голосов
/ 03 июня 2019

Вы действительно можете реализовать свою собственную функцию reduce. И ты почти сделал это:

class DataStore {
  constructor(values) { /* constructor logic */ }

  forEachData(callback) { /* forEach logic */}

  reduce(callback, initialValue) {
    let value = initialValue;
    this.forEachData(function(x){
      value = callback(value, x);
    });

    return value;
  }
}

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

let answer = data_store.reduce(aggregate_op, 0);

Есть ли способ сделать это автоматически, не изобретая колесо? Вроде, как бы, что-то вроде. Это зависит от того, как вы управляете своими ценностями. Вы можете просто наследовать форму Array:

class DataStore extends Array { /* ... */ }

Здесь вы не можете написать свой собственный метод forEachData, вместо этого использовать forEach и не кодировать жестко значения 0 и 1, вместо этого фактически вставить его во внутренний массив данных объекта. Также это будет означать, что вы должны придерживаться семантики массива - без строкового индекса, без разреженных индексов и т. Д.

Если вы можете жить с ограничениями массива, то это простой способ унаследовать множество функций без кодирования. В противном случае вам нужно реализовать свой собственный reduce()

...