Movatterモバイル変換


[0]ホーム

URL:


  1. Веб-технологии для разработчиков
  2. JavaScript
  3. Справочник по JavaScript
  4. The Iterator protocol

This page was translated from English by the community.Learn more and join the MDN Web Docs community.

View in EnglishAlways switch to English

The Iterator protocol

Одно из нововведений стандарта ECMAScript 2015 - протоколы перебора, которые могут реализованы любым объектом, соблюдая при этом определённые правила.

Протоколы перебора

Протоколы перебора включаютthe "iterable" protocol иthe "iterator" protocol.

Протокол "Итерируемый"

Протокол "Итерируемый" позволяет JavaScript объектам определять или настраивать поведение перебора, например, то какие значения перебираются в конструкцииfor..of. Некоторые встроенные типы, такие какArray илиMap, имеют поведение перебора по умолчанию, в то время как другие типы (такие какObject) его не имеют

Для того, чтобы объект былитерируемым, в нем должен быть реализован метод@@iterator, т.е. этот объект (или любой из объектов из егоprototype chain) должен иметь свойство с именемSymbol.iterator:

СвойствоЗначение
[Symbol.iterator]Функция без аргументов, возвращающая объект, соответствующийiterator protocol.

Всякий раз, когда объект подлежит перебору (например, когда в коде встречается циклfor..of), вызывается его метод@@iterator без аргументов, и возвращаемыйiterator используется для получения перебираемых значений.

Протокол "Итератор"

Протокол "Итератор" определяет стандартный способ получения последовательности значений (конечной или бесконечной).

Объект является итератором, если в нем определён методnext() , реализующий следующую логику:

СвойствоЗначение
next

Функция без аргументов, возвращающая объект с двумя свойствами:

  • done (boolean)
    • Принимает значениеtrue если итератор достиг конца итерируемой последовательности. В этом случае свойствоvalue может определятьвозвращаемое значение итератора. Возвращаемые значения объясняются более подробноhere.
    • Принимает значениеfalse если итератор может генерировать следующее значение последовательности. Это эквивалентно не указанному done.
  • value - любое JavaScript значение, возвращаемое итератором. Может быть опущено, еслиdone имеет значениеtrue.

Некоторые итераторы, в свою очередь, итерабельны:

js
var someArray = [1, 5, 7];var someArrayEntries = someArray.entries();someArrayEntries.toString(); // "[object Array Iterator]"someArrayEntries === someArrayEntries[Symbol.iterator](); // true

Примеры использования протокола "итератора"

String является примером встроенного итерабельного объекта:

js
var someString = "hi";typeof someString[Symbol.iterator]; // "function"

По умолчанию итератор строки возвращает символы строки друг за другом:

js
var iterator = someString[Symbol.iterator]();iterator + ""; // "[object String Iterator]"iterator.next(); // { value: "h", done: false }iterator.next(); // { value: "i", done: false }iterator.next(); // { value: undefined, done: true }

Некоторые встроенные конструкции языка, например,spread operator, используют в своей внутренней реализации тот же протокол итерации:

js
[...someString]; // ["h", "i"]

Поведение итератора можно переопределить применив собственный@@iterator:

js
var someString = new String("hi"); // need to construct a String object explicitly to avoid auto-boxingsomeString[Symbol.iterator] = function () {  return {    // this is the iterator object, returning a single element, the string "bye"    next: function () {      if (this._first) {        this._first = false;        return { value: "bye", done: false };      } else {        return { done: true };      }    },    _first: true,  };};

Notice how redefining@@iterator affects the behavior of built-in constructs, that use the iteration protocol:

js
[...someString]; // ["bye"]someString + ""; // "hi"

Встроенная итерируемость

String,Array,TypedArray,Map иSet итерируемы, так как их прототипы содержат@@iterator метод, аObject нет, так как прототипObject не содержит метода@@iterator

Итерируемость определённая пользователем

Мы можем создать итерируемый объект сами:

js
var myIterable = {};myIterable[Symbol.iterator] = function* () {  yield 1;  yield 2;  yield 3;};[...myIterable]; // [1, 2, 3]

Builtin APIs need iterables

Map([iterable]),WeakMap([iterable]),Set([iterable]) andWeakSet([iterable]):

js
var myObj = {};new Map([  [1, "a"],  [2, "b"],  [3, "c"],]).get(2); // "b"new WeakMap([  [{}, "a"],  [myObj, "b"],  [{}, "c"],]).get(myObj); // "b"new Set([1, 2, 3]).has(3); // truenew Set("123").has("2"); // truenew WeakSet(  (function* () {    yield {};    yield myObj;    yield {};  })(),).has(myObj); // true

andPromise.all(iterable),Promise.race(iterable),Array.from()

Синтаксис предполагающий итерируемость

for-of,spread, yield*, destructing - использование данного синтаксиса возможно только если типы данных, к которым он применяется, итерируемы:

js
for (let value of ["a", "b", "c"]) {  console.log(value);}// "a"// "b"// "c"[..."abc"]; // ["a", "b", "c"]function* gen() {  yield* ["a", "b", "c"];}gen().next()[(a, b, c)] = // { value:"a", done:false }  new Set(["a", "b", "c"]);a; // "a"

Non-well-formed iterables

If an iterable's@@iterator method doesn't return an iterator object, then it's a non-well-formed iterable, using it as such is likely to result in runtime exceptions or buggy behavior:

js
var nonWellFormedIterable = {}nonWellFormedIterable[Symbol.iterator] = () => 1[...nonWellFormedIterable] // TypeError: [] is not a function

Объект-генератор является итератором или итерируемым

И тем и другим

js
var aGeneratorObject = function*(){    yield 1;    yield 2;    yield 3;}()typeof aGeneratorObject.next// "function", because it has a next method, so it's an iteratortypeof aGeneratorObject[Symbol.iterator]// "function", because it has an @@iterator method, so it's an iterableaGeneratorObject[Symbol.iterator]() === aGeneratorObject// true, because its @@iterator method return its self (an iterator), so it's an well-formed iterable[...aGeneratorObject]// [1, 2, 3]

Примеры

Простой итератор

js
function makeIterator(array) {  var nextIndex = 0;  return {    next: function () {      return nextIndex < array.length        ? { value: array[nextIndex++], done: false }        : { done: true };    },  };}var it = makeIterator(["yo", "ya"]);console.log(it.next().value); // 'yo'console.log(it.next().value); // 'ya'console.log(it.next().done); // true

Бесконечный итератор

js
function idMaker() {  var index = 0;  return {    next: function () {      return { value: index++, done: false };    },  };}var it = idMaker();console.log(it.next().value); // '0'console.log(it.next().value); // '1'console.log(it.next().value); // '2'// ...

С генератором

js
function* makeSimpleGenerator(array) {  var nextIndex = 0;  while (nextIndex < array.length) {    yield array[nextIndex++];  }}var gen = makeSimpleGenerator(["yo", "ya"]);console.log(gen.next().value); // 'yo'console.log(gen.next().value); // 'ya'console.log(gen.next().done); // truefunction* idMaker() {  var index = 0;  while (true) yield index++;}var gen = idMaker();console.log(gen.next().value); // '0'console.log(gen.next().value); // '1'console.log(gen.next().value); // '2'// ...

Спецификации

Specification
ECMAScript® 2026 Language Specification
# sec-iteration

Смотрите также

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp