Что такое итератор?
удовлетворитьпротокол итератораОбъект.
протокол итератора:
объектnextМетод - это функция без аргументов, которая возвращает объект, который имеетdoneа такжеvalueДва свойства:
-
done(boolean):- если итератор прошел итерируемую последовательность
true. В настоящее времяvalueможет описывать возвращаемое значение этого итератора. - Если итератор может дать следующее значение в последовательности, то
false.这等效于连同doneСвойства также не указаны.
- если итератор прошел итерируемую последовательность
-
value: любое значение JavaScript, возвращаемое итератором.doneдляtrueможно опустить.
ES5 реализует простой итератор:
function createIterator(items) {
var i = 0;
return {
next: function() {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
// 之后的所有调用
console.log(iterator.next()); // "{ value: undefined, done: true }"
Что такое итерируемый объект (Iterable)?
удовлетворитьИтерируемый протоколОбъект является итерируемым объектом.
Итерируемый протокол:
объект[Symbol.iterator]value — это функция без параметров, которая возвращает итератор.
В ES6 все объекты коллекции (Array,Setа такжеMap)так же какString,argumentsОба являются итерируемыми объектами, и все они имеют итераторы по умолчанию.
Итерируемые объекты могут использоваться в следующих операторах:
for (let value of ['a', 'b', 'c']) {
console.log(value);
}
// "a"
// "b"
// "c"
[...'abc']; // ["a", "b", "c"]
console.log(...['a', 'b', 'c']); // ["a", "b", "c"]
function* gen() {
yield* ['a', 'b', 'c'];
}
gen().next(); // { value: "a", done: false }
let [a, b, c] = new Set(['a', 'b', 'c']);
a; // 'a'
пониматьfor...ofцикл
for...ofПринимает Iterable или значение, которое может быть приведено/обернуто в Iterable (например, 'abc'). При обходе,for...ofполучит итерируемый объект[Symbol.iterator](), вызовите next() для итератора последовательно, пока итератор не вернет значение объекта.doneсобственностьtrueКогда обход заканчивается, значение не обрабатывается.
for...ofПример цикла:
var a = ["a","b","c","d","e"];
for (var val of a) {
console.log( val );
}
// "a" "b" "c" "d" "e"
Например, преобразуется в общую петлю, эквивалентно вышеуказанномуfor...ofцикл:
var a = ["a","b","c","d","e"];
for (var val, ret, it = a[Symbol.iterator]();
(ret = it.next()) && !ret.done;
) {
val = ret.value;
console.log( val );
}
// "a" "b" "c" "d" "e"
сделать итератор итерируемым
существуетчто такое итераторраздел, мы настраиваем простую функцию, которая генерирует итераторcreateIterator, но итератор, сгенерированный этой функцией, не реализует итерируемый протокол, поэтому его нельзя использовать вfor...ofИ т.д., используемые в грамматике. Это может быть достигнуто протоколом итерации для объекта, в[Symbol.iterator]Функция возвращает сам итератор.
function createIterator(items) {
var i = 0;
return {
next: function () {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
},
[Symbol.iterator]: function () { return this }
};
}
var iterator = createIterator([1, 2, 3]);
console.log(...iterator)
Что такое генератор (генератор)?
генераторная функция
Генераторная функция (GeneratorFunction)способен вернутьГенератор (Генератор)Функция.生成器函数由放在 function 关键字之后的一个星号( * )来表示,并能使用新的 yield 关键字。
function *aGeneratorfunction(){
yield 1
yield 2
yield 3
};
var aGeneratorObject = aGeneratorfunction()
// 生成器对象
aGeneratorObject.toString() // "[object Generator]"
Объекты Builder являются как итераторы и итеративные объекты
function *aGeneratorfunction(){
yield 1
yield 2
yield 3
};
var aGeneratorObject = aGeneratorfunction()
// 满足迭代器协议,是迭代器
aGeneratorObject.next() // {value: 1, done: false}
aGeneratorObject.next() // {value: 2, done: false}
aGeneratorObject.next() // {value: 3, done: false}
aGeneratorObject.next() // {value: undefined, done: true}
// [Symbol.iterator]是一个无参函数,该函数执行后返回生成器对象本身(是迭代器),所以是可迭代对象
aGeneratorObject[Symbol.iterator]() === aGeneratorObject // true
// 可以被迭代
var aGeneratorObject1 = aGeneratorfunction()
[...aGeneratorObject1] // [1, 2, 3]
Взамен Строитель
перебрать возвращаемый объектdoneзначениеtrueИтерация заканчивается, когдаvalueиметь дело с.
function *createIterator() {
yield 1;
return 42;
yield 2;
}
let iterator = createIterator();
iterator.next(); // {value: 1, done: false}
iterator.next(); // {value: 42, done: true}
iterator.next(); // {value: undefined, done: true}
doneКогда значение истинно, итерация завершается, и итерация не обрабатывает значение. Таким образом, для этого обхода итератора значение 42 не будет обработано.
let iterator1 = createIterator();
console.log(...iterator); // 1
Добавить к[Symbol.iterator]СделатьObjectповторяемый
согласно сИтерируемый протокол,ДатьObjectДобавлен прототип[Symbol.iterator]Нет возвращаемого значения - это эталонная функция объекта, объект возвращается соответствие протокола итератора.
Object.prototype[Symbol.iterator] = function () {
var i = 0
var items = Object.entries(this)
return {
next: function () {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
}
}
var a = {
name: 'Jimmy',
age: 18,
job: 'actor'
}
console.log(...a) // [ 'name', 'Jimmy' ] [ 'age', 18 ] [ 'job', 'actor' ]
Упростите свой код с помощью генераторов:
Object.prototype[Symbol.iterator] = function* () {
for (const key in this) {
if (this.hasOwnProperty(key)) {
yield [key, this[key]];
}
}
}
var a = {
name: 'Jimmy',
age: 18,
job: 'actor'
}
console.log(...a) // [ 'name', 'Jimmy' ] [ 'age', 18 ] [ 'job', 'actor' ]
делегат генератораyield*
function* g1() {
yield 1;
yield 2;
}
function* g2() {
yield* g1();
yield* [3, 4];
yield* "56";
yield* arguments;
}
var generator = g2(7, 8);
console.log(...generator); // 1 2 3 4 "5" "6" 7 8
последний пример
Проанализируйте следующий код:
function* fibs() {
var a = 0;
var b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(first, second, third, fourth, fifth, sixth);
В этом кодеfibsгенератор, генерирующий бесконечно длинные последовательности Фибоначчи,[a, b] = [b, a + b]Это назначение обмена назначения реструктуризации (= присвоение рассчитывается справа налево, поэтому сначала вычислите правую сторону.a+b, а затем структура, каждая из которых имеет эффект назначения обмена), написанная на ES5 для создания массива конечной длины следующим образом:
function fibs1(n) {
var a = 0;
var b = 1;
var c = 0;
var result = []
for (var i = 0; i < n; i++) {
result.push(a);
c = a;
a = b;
b = c + b;
}
return result;
}
console.log(fibs1(6)) // [0, 1, 1, 2, 3, 5]
И в первом фрагменте кода изfibs()Первые шесть значений деконструируются из итератора (генератор — это подмножество итератора), пример кода следующий:
function* fibs2(n) {
var a = 0;
var b = 1;
for (var i = 0; i < n; i++) {
yield a;
[a, b] = [b, a + b];
}
}
console.log(...fibs2(6))
Зачем использовать итераторы, генераторы и каковы преимущества?
...пока не разобрался
Выше есть много частей, которые я понимаю лично, добро пожаловать на исправление ошибок (* ̄︶ ̄)
Ссылаться на: