Добавить Автора
переведено изnuggets.capable/post/684490…
В этой статье в основном говорится оES6
изIterator
, цель состоит в том, чтобы понять его концепцию, функции и существующие приложения и, наконец, применить его на практике.
Iterator
Можно сказать, что это очень важная функция ES6, а также краеугольный камень многих других функций.
ЗачемIterator
Такой высокий статус?
начать с переменной
var arr = ['红','绿','蓝'];
Это обычный массив, если я хочу получить каждый элемент его данных, что мне делать?
Это непросто, просто используйте цикл for.Если вы считаете, что цикл низкий, используйте forEach.
ок, сразу получай код
//for 循环
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
//forEach
arr.forEach(item => {
console.log(item);
});
// 结果 略
хорошо, нет проблем.
Тогда продолжим, посмотрим на код ниже. Учитывая строку, что, если я хочу вывести каждый символ?
var str = '1234567890';
Что-то в этом не так, это просто смешно.
Вы можете использовать цикл for in или цикл for для обработки в виде массива.
Код сейчас
//for in
for (var s in str) {
console.log(str[s]);
//s 是 属性名称【key】
}
//转为数组
for (var i = 0; i < str.length; i++) {
console.log(str[i]);
}
//或者转换为数组
Array.prototype.slice.call(str);
ноfor in
Он не используется для получения данных, он будет проходить через все перечисляемые свойства объекта, включая свои собственные и цепочку прототипов, так что это не гарантируется.
эммм.... нет проблем, продолжим.
См. приведенный ниже код, учитываяmap
объект, а затем вывести каждый элемент его данных.
var map = new Map();
map.set('zhang', '1000w');
map.set('liu', '200w');
map.set('sun', '100w');
использоватьforEach
Вот и все.
map.forEach((val,key) => {
console.log(val,key);
})
Увидев здесь столько простых и возмутительных вопросов, наверное, я не могу усидеть на месте, и мне приходится поднимать стол и уходить. Пожалуйста, подождите немного и медленно посмотрите вниз.
проблема найдена
Ну, в нескольких простых вопросах на предыдущем шаге наша операция состоит в том, чтобы получить все их данные.
Конечно, есть много способов и способов добиться этого.for 循环
,forEach
,for in
Ла.
Но нашли ли мы проблему, или мы смотрим на нее с более высокого измерения, на самом деле эти методы не универсальны, то есть вышеперечисленные типы данных коллекции не могут быть получены с помощью единого метода обхода.
Кто сказал, что его можно унифицировать, его можно использоватьforEach
для перебора массива иmap
Он поддерживается сам по себе, и я могу напрямую преобразовать строку в массив.
хорошо, в этом нет ничего плохого.
Но каждый раз его приходится конвертировать, инкапсулировать и, возможно, врезать в прототип.
Есть ли лучший общий метод, который сделает его более удобным и крутым для разработчиков?
Ответ - да,es5
когда он не появился, обновите доes6
Вот оно.
NB для откусить
Этот способ унифицированного обхода различных структур данныхes6
изfor of
цикл.
for of
петля и древнийfor 循环
Очень похожий. Разве это не просто новый синтаксис.
Цитируя предложение из книги г-на Жуана, я думаю, вы поймете его с первого взгляда.
В ES6 появился цикл for...of, заимствованный из языков C++, Java, C# и Python. Как единый способ обхода всех структур данных. Ключ заключается в унификации, а другой - в непосредственном получении значения, упрощении операции и отсутствии необходимости объявлять и поддерживать какие-либо переменные или преобразовывать данные.
оказалосьfor of
так корова,for
Вы можете делать то, с чем не может справиться цикл.
Зачемfor of
Благодаря этой возможности можно обеспечить единый метод сбора данных для различных структур данных.
for of
Действительно ли он такой мощный, и какой механизм стоит за ним?
фактическиfor of
Не очень сильный, он простоES6
Просто новый синтаксис.
Не все объекты можно использоватьfor of
, только если реализоватьIterator
Объекты интерфейса можно использовать толькоfor of
для обхода значения.
такfor of
Просто синтаксический сахар, настоящий геройIterator
.
What ? Iterator.....
Дебют главного героя - Iterator iterator
Iterator
Это интерфейс, целью которого является предоставление унифицированного механизма доступа к данным для различных структур данных. также можно понимать какIterator
Интерфейс в основномfor of
сервировка, дляfor...of
потреблять.
На самом деле функция Iterator существовала много лет назад во многих внутренних языках, таких как java, C++, C# и т. д.
Поскольку это интерфейс, как мы должны реализовать этот интерфейс? Как выглядят правила реализации?
потому чтоjavascript
В языке нет понятия интерфейса, здесь мы можем понять, что это особый вид объекта — объект-итератор, а метод, возвращающий этот объект, называется методом-итератором.
Во-первых, как объект этот объект имеетnext
метод, каждый вызовnext
методы возвращают значение результата.
Полученное значение представляет собойobject
, содержит два свойства,value
а такжеdone
.
value
Указывает конкретное возвращаемое значение,done
Это логическое значение, указывающее, является ли набор прохождений или если есть последующие данные, доступные данные, доступные данныеtrue
, иначе возвратfalse
.
Кроме того, внутри будет поддерживаться указатель, указывающий на расположение текущей коллекции, и каждый вызов будетnext
метод, указатель переместится на одну позицию назад (представьте, что это индекс массива).
Посмотрите на реализацию кода
function getIterator(list) {
var i = 0;
return {
next: function() {
var done = (i >= list.length);
var value = !done ? list[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
var it = getIterator(['a', 'b', 'c']);
console.log(it.next());// {value: "a", done: false}
console.log(it.next());// {value: "b", done: false}
console.log(it.next());// {value: "c", done: false}
console.log(it.next());// "{ value: undefined, done: true }"
console.log(it.next());// "{ value: undefined, done: true }"
console.log(it.next());// "{ value: undefined, done: true }"
Приведенный выше код представляет собой смоделированную реализацию, основанную на базовой концепции итераторов.
-
getIterator
метод возвращает объект - итерируемый объект -
объект имеет
next
метод,next
Указатель хранится внутри метода через замыканиеi
ценность каждого звонкаnext
методi
значение будет+1
. -
затем согласно
i
Значение извлекает данные из массива какvalue
, а затем по индексу получитьdone
ценность . -
когда
i=3
Когда максимальный индекс массива превышен, доступные данные не возвращаются.true
, обход завершен.
повторяемый объект
Вот примерно разобралисьIterator
и как создать объект итератора. Но он иfor of
Что это значит?
для рабочего механизма
когдаfor of
При выполнении движок автоматически вызовет это во время цикла对象上的迭代器方法
, который, в свою очередь, выполняет объект итератораnext
метод, будетnext
Возвращаемое значение присваиваетсяfor of
переменная для получения определенного значения.
Я думаю, что приведенное выше предложение содержит важную информацию - «Методы итератора для объектов».
Реализовать итерируемые объекты
Как может быть метод итератора для объекта?
ES6
В положениях, развернутых до тех пор, пока свойства объектаIterator
Интерфейс, в виде добавления к объектуSymbol.iterator
свойство, это свойство указывает на метод итератора, который возвращает специальный объект — объект итератора.
Объект, который развертывает это свойство и реализует метод итератора, называется可迭代对象
.
В этот момент объект является итерируемым, то есть его можноfor of
траверс.
Symbol.iterator — выражение, возвращающее свойство итератора объекта Symbol, которое является предопределенным специальным значением типа Symbol.
взять каштан
Обычные предметы не могут бытьfor of
Обход, прямое потребление сообщит об ошибке.
var obj = {};
for (var k of obj) {
}
obj не является итерируемым объектом.
Тогда давайте сделаем из объекта итерабельный объект и реализуем его по протоколу, то есть по регламенту.
iterableObj
развернуть на объектеSymbol.iterator
свойство, а затем создать для него метод итератора.Мы уже упоминали правила итераторов выше.
var iterableObj = {
items: [100,200,300],
[Symbol.iterator]: function() {
var self = this;
var i = 0;
return {
next: function () {
var done = (i >= self.items.length);
var value = !done ? self.items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}}
//遍历它
for (var item of iterableObj) {
console.log(item);//100,200,300
}
Это так просто, вышеприведенный объект является итерируемым объектом, который может использоватьсяfor of
потребляется.
Сценарии собственных приложений Iterator
Вернемся к началуfor of
для обхода строк, массивов, карт мы не разворачивали для нихIterator
интерфейс, который все еще можно использоватьfor of
траверс.
Это потому, что вES6
Некоторые объекты в этом интерфейсе уже развернули этот интерфейс по умолчанию, и вы можете использовать его без какой-либо обработки.for of
для обхода значения.
Не верю? Эй, ты такой жесткий, я не хочу, чтобы ты говорил - письмо, я хочу, чтобы я говорил - письмо.
Посмотрите, сможете ли вы получить их итераторы.
数组
//数组
var arr = [100,200,300];
var iteratorObj = arr[Symbol.iterator]("Symbol.iterator");
//得到迭代器方法,返回迭代器对象
console.log(iteratorObj.next());
console.log(iteratorObj.next());
console.log(iteratorObj.next());
console.log(iteratorObj.next());
字符串
Поскольку значение самой строки упорядочено и имеет характеристики массива, оно поддерживает доступ по индексу, поэтому оно также развертывается по умолчанию.iterator
интерфейс.
var str = 'abc';
var strIteratorObj = str[Symbol.iterator]("Symbol.iterator");//得到迭代器
console.log(strIteratorObj.next());
console.log(strIteratorObj.next());
console.log(strIteratorObj.next());
console.log(strIteratorObj.next());
Или непосредственно на прототипе, чтобы увидеть, можно ли развернуть это свойство.
arguments
массивный
внутри функцииarguments
похож на массив, он также поддерживаетfor of
, потому что он также развернут внутриIterator
интерфейс.
Мы все знаем, что объект не развертывает этот интерфейс по умолчанию, поэтомуarguments
Это свойство находится не в прототипе, а в свойствах самого объекта.
function test() {
var obj = arguments[Symbol.iterator]("Symbol.iterator");
console.log(arguments.hasOwnProperty(Symbol.iterator));
console.log(arguments);
console.log(obj.next());
}
test(1,2,3);
Подводя итог, можно сказать, что объекты, для которых развернут интерфейс Iterator по умолчанию, в основном включают в себя массивы, строки, наборы, карты и объекты, подобные массивам (такие как объекты аргументов, объекты DOM NodeList.
Проверка кода незначительна, это рутина, особо нечего сказать
Другая функция Iterator
Iterator
Помимо предоставления унифицированного метода доступа к данным для различных структур данных, нашли ли вы другое применение?
Это настраиваемость данных, потому что мы можем управлять итератором по желанию.value
стоимость.
Например: сам массив является итерируемым, мы можем переопределить его итератор по умолчанию.
var arr = [100,200,300];
for(var o of arr) {
console.log(o);
}
for of
Выход массива по умолчанию выглядит следующим образом
После нашей трансформации
var arr = [100,200,300];
arr[Symbol.iterator] = function () {
var self = this;
var i = 0;
return {
next: function () {
var done = (i >= self.length);
var value = !done ? self[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
for (var o of arr) {
console.log(o);
}
Почему объекты не развертываются по умолчанию
Объекты могут иметь различные свойства, в отличие от массивов, значения которых упорядочены.
Поэтому при обходе мы не знаем, как определить их порядок, поэтому нам нужно реализовать его вручную по ситуации.
[Сообщество] Общественное внимание ВНИМАНИЕ IVWEB Номер для просмотра новейших технологических журналов, вы лучше сегодня, чем вчера!
Распространение
для прерывания
Мы все знаем обычноеfor
Цикл может быть прерван в любой момент, затемfor of
Является ли это возможным?
Ответ - да,for of
механизм учитываетfor
а такжеforEach
.
Итераторы должны бытьnext
В дополнение к методу, есть два дополнительных методаreturn
а такжеthrow
метод.
еслиfor of
Если цикл выйдет раньше, он будет вызван автоматическиreturn
Метод следует отметить, чтоreturn
Метод должен иметь возвращаемое значение, а возвращаемое значение должно быть единицей.object
.
ps: выйдите, бросив исключение, оно будет выполнено первымreturn
метод выдает исключение.
var iterableObj = {
items: [100,200,300],
[Symbol.iterator]: function () {
var self = this;
var i = 0;
return {
next: function () {
var done = (i >= self.items.length);
var value = !done ? self.items[i++] : undefined;
return {
done: done,
value: value
};
},
return() {
console.log('提前退出');
return {
//必须返回一个对象
done: true
}
}
};
}}
for (var item of iterableObj) {
console.log(item);
if(item === 200) {
break;
}}
for (var item of iterableObj) {
console.log(item);
throw new Error();
}
Метод ps:throw здесь не упоминается, это не то место, где он используется, увидимся в следующей статье.
больше, чем для
Кромеfor of
При выполнении он автоматически вызывает объектIterator
метод, тоES6
Есть ли другие грамматические формы?
присваивание деструктуризации
При деструктуризации и назначении итерируемого объекта он будет вызываться по умолчаниюSymbol.iterator
метод.
//字符串
var str = '12345';
var [a,b] = str;
console.log(a,b);// 1 2
//map
var map = new Map();
map.set('我','前端');
map.set('是','技术');
map.set('谁','江湖');
map.set('作者','zz_jesse');
var [d,e] = map;
console.log(d,e);
//["我", "前端"] ["是", "技术"]....
Точно так же, если обычный объект будет уничтожен, будет сообщено об ошибке.
Потому что обычные объекты не являются итерируемыми.
var [d, e] = {name: 'zhang'};
Деструктурирование присваивания из пользовательского итерируемого объекта.
var iterableObj = {
items: ['红','绿','蓝'],
[Symbol.iterator]: function () {
var self = this;
var i = 0;
return {
next: function () {
var done = (i >= self.items.length);
var value = !done ? self.items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}}
var [d,e] = iterableObj;
console.log(d,e);//红 绿
Значение переменной, присвоенное деструктуризацией, является возвращаемым значением следующего метода объекта итератора и возвращается по порядку.
спред оператор
Выполнение оператора распространения (...) также вызывает его по умолчаниюSymbol.iterator
метод для преобразования текущего объекта итерации в массив.
//字符串
var str = '1234';
console.log([...str]);//[1, 2, 3, 4] 转换为数组
//map 对象
var map = new Map([[1, 2], [3, 4]]);
[...map] //[[1, 2], [3, 4]
//set 对象
var set = new Set([1, 2, 3]);
[...set]//[1, 2, 3]
Общие обычные объекты не могут быть преобразованы в массивы.
var obj = {name: 'zhang'};
[...obj]//报错
как источник данных
В качестве источника данных некоторых данных, например, параметр некоторых методов API должен получать массив, и он по умолчанию будет вызывать свой собственный итератор.
Например: Set, Map, Array.from и т. д.
//为了证明,先把一个数组的默认迭代器给覆盖掉
var arr = [100, 200, 300];
arr[Symbol.iterator] = function () {
var self = this;
var i = 0;
return {
next: function () {
var done = (i >= self.length);
var value = !done ? self[i++] : undefined;
return {
done: done,
value: value+'前端技术江湖'
//注意这里
};
}
};
}
for (var o of arr) {
console.log(o);
}
// 100前端技术江湖
// 200前端技术江湖
// 300前端技术江湖
перезаписанный
//生成 set 对象
var set = new Set(arr);
//调用 Array.from方法
Array.from(arr);
ключевые слова yield*
За yield* следует проходимая структура, которая также вызывает функцию итератора при выполнении.
let foo = function* () {
yield 1;
yield* [2,3,4];
yield 5;
};
Урожайность необходимо подчеркнуть, и она будет подробно описана в следующем разделе.
Определить, является ли объект итеративным
Поскольку правила для итерируемых объектов должны быть развернуты на объектеSymbol.iterator
Атрибут, то мы можем в основном использовать этот атрибут, чтобы определить, является ли объект итерируемым объектом, а затем мы можем узнать, можно ли его использовать.for of
ценится.
function isIterable(object) {
return typeof object[Symbol.iterator] === "function";
}
console.log(isIterable('abcdefg')); // true
console.log(isIterable([1, 2, 3]));// true
console.log(isIterable("Hello"));// true
console.log(isIterable(new Map())); // true
console.log(isIterable(new Set()));// true
console.log(isIterable(new WeakMap())); // false
console.log(isIterable(new WeakSet()));// false
Суммировать
ES6
Появление множества новых структур данных, таких какMap
,Set
, поэтому для удобства сбора данных добавлен единый способ получения данных.for of
. а такжеfor of
При выполнении движок автоматически вызовет итератор объекта, чтобы получить значение.
Не все объекты поддерживают этот метод, он должен быть реализованIterator
Только интерфейсы могут, такие объекты мы называем итерируемыми объектами.
Итератор реализован в соответствии с итерируемым протоколом, и может быть реализован протокол итератора.
В дополнение к унифицированному методу доступа к данным вы также можете настроить содержимое полученных данных, как хотите, до тех пор, пока вам это нужно.
Итератор — это метод, который возвращает объект итератора.
Iterables развернутIterator
Объект интерфейса с правильными методами итератора.
Он используется во многих местах в ES6.Iterator
, Обычно вы можете уделять больше внимания наблюдению, думать на один шаг больше.
и конец и начало
На этом этапе мы можем настроить итератор по правилам итератора, но процесс реализации немного сложен, ведь нам нужно самим поддерживать внутренний указатель, логической обработки много, и ошибки будут неизбежно происходят.
Есть ли более элегантный способ сделать это?
Да, то есть - Генератор - Генератор.
let obj = {
*[Symbol.iterator]( "Symbol.iterator") {
yield 'hello';
yield 'world';
}
};
for (let x of obj) {
console.log(x);
}
// "hello"
// "world"
Видно, что он очень лаконичен и может генерировать итератор без лишнего кода.
Помимо того, что он является синтаксическим сахаром для генерации итераторов, он обладает и более магическими возможностями.
Такая забавная способность обязательно будет разбита, но сегодня уже поздно, поздно ложиться спать вредит моему телу, на этот раз я сначала это исправлю.Iterator
.
в следующий разGenerator
.
упражняться
Если вы считаете, что эта статья полезна, вы можете попробовать выполнить следующие упражнения, чтобы углубить свое понимание.
-
Напишите объект Iterator.
-
Настройте итерируемый объект.
-
скажи, что ты прав
Iterator
понимание, под кратким выводом.
использованная литература
[1] Голод 6. Ruan Yifeng.com/#docs/ITER A… Голод 6. Ruan Yifeng.com/#docs/ITER A…
[2] developer.Mozilla.org/this-cn/docs/… developer.Mozilla.org/this-cn/docs/…
[3] блог woo woo woo.cn на.com/smallmatch… блог woo woo woo.cn на.com/smallmatch…