1. Итератор
Исходные структуры данных JavaScript, которые представляют «коллекции», в основном представляют собой массивы и объекты.ES6 добавляет Map и Set. Это требует единого механизма интерфейса для обработки всех различных структур данных. Итераторы — один из таких механизмов. Это интерфейс, обеспечивающий унифицированный механизм доступа к множеству различных структур данных.Любая структура данных может завершить операцию обхода до тех пор, пока развернут интерфейс Iterator (то есть все элементы структуры данных обрабатываются по очереди)..
1. Роль итератора:
- Обеспечить единый и удобный интерфейс доступа к различным структурам данных;
- Позволяет расположить элементы структуры данных в определенном порядке.
- ES6 создал новую команду обхода цикла for...of, а интерфейс Iterator в основном используется для for...of потребления.
2. Нативные данные с интерфейсом iTerator (для обхода)
- Array
- установить контейнер
- контейнер карты
- String
- функция объекта аргументов
- Объект NodeList
let arr3 = [1, 2, 'kobe', true];
for(let i of arr3){
console.log(i); // 1 2 kobe true
}
let str = 'abcd';
for(let item of str){
console.log(item); // a b c d
}
function fun() {
for (let i of arguments) {
console.log(i) // 1 4 5
}
}
fun(1, 4, 5)
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
console.log(e);
}
// Gecko
// Trident
// Webkit
- Создайте объект-указатель, указывающий на начало структуры данных.
- При первом вызове метода next указатель автоматически указывает на первый элемент структуры данных.
- Затем непрерывно вызывается следующий метод, и указатель будет двигаться назад, пока не укажет на последний элемент.
- Каждый вызов следующего метода возвращает объект, содержащий значение и выполнено, {значение: значение текущего члена, выполнено: логическое значение}
- value указывает значение текущего члена, а логическое значение, соответствующее done, указывает, завершен ли обход текущей структуры данных.
- Когда обход заканчивается, возвращаемое значение не определено, а выполненное значение равно true.
4. Напишите итератор вручную
function myIterator(arr) {
let nextIndex = 0
return {
next: function() {
return nextIndex < arr.length
? { value: arr[nextIndex++], done: false }
: { value: undefined, value: true }
}
}
}
let arr = [1, 4, 'ads']// 准备一个数据
let iteratorObj = myIterator(arr)
console.log(iteratorObj.next()) // 所有的迭代器对象都拥有next()方法,会返回一个结果对象
console.log(iteratorObj.next())
console.log(iteratorObj.next())
console.log(iteratorObj.next())
5. Обратите внимание
① цикл for of не поддерживает обход обычных объектов
var obj = { a: 2, b: 3 }
for (let i of obj) {
console.log(i) // Uncaught TypeError: obj is not iterable
}
Свойства Symbol.iterator объекта указывают на метод по умолчанию для обхода объекта.При использовании for одной структуры данных для обхода сначала найдите Symbol.iterator, идите найдите обход, не нашел слова не может пройти, советыUncaught TypeError: XXX is not iterable
② При использовании оператора расширения (...) или деструктуризации присвоений массивам и структурам Set метод Symbol.iterator вызывается по умолчанию.
let arr1 = [1,3]
let arr2 = [2,3,4,5]
arr2 = [1,...arr2,6]
console.log(arr2) // [1, 2, 3, 4, 5, 6]
2. Генератор
1. Концепция
- Функция генератора — это решение для асинхронного программирования, предоставляемое ES6.
- .
- Помимо конечного автомата, функция Generator также является функцией генерации объекта обхода..
- Приостанавливаемые функции (ленивые вычисления), yield можно приостановить, можно запустить следующий метод. Каждый раз, когда он возвращает результат выражения после yield
2. Особенности
- Между ключевым словом функции и именем функции стоит звездочка;
- Используйте выражения доходности внутри корпуса функции, чтобы определить разные внутренние состояния
function* generatorExample(){
console.log("开始执行")
yield 'hello';
yield 'generator';
}
// generatorExample()
// 这种调用方法Generator 函数并不会执行
let MG = generatorExample() // 返回指针对象
MG.next() //开始执行 {value: "hello", done: false}
Функция Generator выполняется по частям, вызывая следующий метод, чтобы начать выполнение внутренней логики функции, останавливаясь, когда встречается выражение yield, и возвращая{value: yield后的表达式结果/undefined, done: false/true}
, Повторный вызов следующего метода начнется с выхода на последней остановке до конца.
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()// { value: 'hello', done: false }
hw.next()// { value: 'world', done: false }
hw.next()// { value: 'ending', done: true }
hw.next()// { value: undefined, done: true }
При первом вызове функция Generator начинает выполняться до тех пор, пока не встретится первое выражение yield. Следующий метод возвращает объект, атрибут value которого является значением текущего выражения yield hello, а значение атрибута done равно false, что указывает на то, что обход не завершен.
При втором вызове функция Generator продолжает работу с того места, где остановилось последнее выражение yield, до следующего выражения yield. Атрибут value объекта, возвращаемый методом next, является миром значений текущего выражения yield, а значение атрибута done равно false, что указывает на то, что обход не завершен.
В третьем вызове функция Generator выполняется с места, где остановилось последнее выражение yield, до оператора return (если оператора return нет, он выполняется до конца функции). Свойство value объекта, возвращаемое методом next, представляет собой значение выражения, следующего сразу за оператором return (если нет оператора return, значение свойства value не определено), а значение свойства done равно true, свидетельствующий о том, что обход завершен.
Четвертый вызов, в это время работает функция Генератор, а метод next возвращает значение объекта в неопределенное, свойство DONE имеет значение TRUE. Следующий метод вызывается снова, и возвращается это значение.
3. параметры следующего прохода
Само выражение yield не возвращает значение или всегда возвращает значение undefined. Следующий метод может принимать один параметр, который будет использоваться как возвращаемое значение предыдущего выражения yield.
function* generatorExample () {
console.log('开始执行')
let result = yield 'hello'
console.log(result)
yield 'generator'
}
let MG = generatorExample()
MG.next()
MG.next()
// 开始执行
// undefined
// {value: "generator", done: false}
Когда значение не передается, результат по умолчанию не определен.Далее мы передаем параметр второму next и смотрим, что получается на выходе?
function* generatorExample () {
console.log('开始执行')
let result = yield 'hello'
console.log(result)
yield 'generator'
}
let MG = generatorExample()
MG.next()
MG.next(11)
// 开始执行
// 11
// {value: "generator", done: false}
4. Связь с интерфейсом Iterator
Выше мы упоминали, что объект не имеет интерфейса итератора, и при обходе с помощью for...of будет сообщено об ошибке.
let obj = { username: 'kobe', age: 39 }
for (let i of obj) {
console.log(i) // Uncaught TypeError: obj is not iterable
}
Так как ходок является генератором функции, генерирующей функцию можно присвоить объекту Symbol.iterator Generator свойства, чтобы объект имел интерфейс Iterator.
let obj = { username: 'kobe', age: 39 }
obj[Symbol.iterator] = function* myTest() {
yield 1;
yield 2;
yield 3;
};
for (let i of obj) {
console.log(i) // 1 2 3
}
В приведенном выше коде функция, назначенная свойствам генератора Symbol.iterator, чтобы объект obj имел интерфейс Iterator, может быть for или traversed.
5.Асинхронное приложение генератора
Потребности бизнеса:
- В случае сбоя получения новостного контента нет необходимости повторно отправлять запрос.
Как реализовать (основной код внешнего интерфейса выглядит следующим образом):
function* sendXml() {
// url为next传参进来的数据
let url = yield getNews('http://localhost:3000/news?newsId=2');//获取新闻内容
yield getNews(url);//获取对应的新闻评论内容,只有先获取新闻的数据拼凑成url,才能向后台请求
}
function getNews(url) {
$.get(url, function (data) {
console.log(data);
let commentsUrl = data.commentsUrl;
let url = 'http://localhost:3000' + commentsUrl;
// 当获取新闻内容成功,发送请求获取对应的评论内容
// 调用next传参会作为上次暂停是yield的返回值
sx.next(url);
})
}
let sx = sendXml();// 发送请求获取新闻内容
sx.next();
Если вы считаете, что статья немного полезна для вас, добро пожаловать вмой блог на гитхабеСтавьте лайк и подписывайтесь, большое спасибо!