Можно ли реализовать в ES5 JavaScript ленивый итератор для ключей объекта без одновременной загрузки всех ключей объекта в память? - PullRequest
0 голосов
/ 05 марта 2019

Я хочу написать функцию ES5 JavaScript (т.е. без генераторов или Symbol.iterator), которая выполняет то, что выполняет следующая функция генератора в ES6:

function *keys(o) {
  for (let key in o)
    yield key
}

Я хочу вернуть ленивый итератор без загрузки всех ключей в память за один раз , поэтому Object.keys находится вне таблицы, так как возвращает массив ключей. Тем не менее, я не могу понять, как это сделать.

Я впал в отчаяние, поэтому начал изучать, как генераторы переносятся в версии JavaScript, которые их не поддерживают. Если вы введете приведенную выше функцию генератора в Регенератор Facebook , вы получите следующий вывод:

var _marked =
/*#__PURE__*/
regeneratorRuntime.mark(keys);

function keys(o) {
  var key;
  return regeneratorRuntime.wrap(function keys$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          _context.t0 = regeneratorRuntime.keys(o);

        case 1:
          if ((_context.t1 = _context.t0()).done) {
            _context.next = 7;
            break;
          }

          key = _context.t1.value;
          _context.next = 5;
          return key;

        case 5:
          _context.next = 1;
          break;

        case 7:
        case "end":
          return _context.stop();
      }
    }
  }, _marked, this);
}

После прочтения этого вывода я подумал, что реализация regeneratorRuntime.keys может содержать ответ, но, похоже, эта функция загружает все ключи в память одновременно:

exports.keys = function(object) {
  var keys = [];
  for (var key in object) {
    keys.push(key);
  }
  keys.reverse();

  // Rather than returning an object with a next method, we keep
  // things simple and return the next function itself.
  return function next() {
    while (keys.length) {
      var key = keys.pop();
      if (key in object) {
        next.value = key;
        next.done = false;
        return next;
      }
    }

    // To avoid creating an additional object, we just hang the .value
    // and .done properties off the next function object itself. This
    // also ensures that the minifier will not anonymize the function.
    next.done = true;
    return next;
  };
};

Есть идеи?

1 Ответ

0 голосов
/ 05 марта 2019

Нет, нет способа создать ленивый итератор свойств.В ES6 было Reflect.enumerate, а функции генератора позволяют записать этот помощник keys, но в ES5 такого средства не существует - учитывая, что в ES5 не было никакой концепции итератора, это неудивительно.

...