for of 循环语句
for...of
循环语句
ES6
为实现了迭代器接口的数据提供了统一访问访机制:新增了一个循环语句 — for...of
循环语句;该语句会自动寻找Iterator
接口。所以数据只要实现了Iterator
接口,该数据就是可以被遍历的;该接口默认部署在Symbol.iterator
属性上
原生的数据实现了迭代器接口的有:Array
,String
,Map
,Set
,TypedArray
(如 Int8Array
),arguments
,NodeList
, HTMLCollection
等
// 字符串迭代器接口
console.log(String.prototype[Symbol.iterator])
//类数组 迭代器
let arr = new Int8Array(4)
arr[0] = 10
arr[1] = 100
// arr[2] = 1000
arr[2] = 2 ** 7 - 1
console.log(arr)
//参数
function demo() {
console.log(arguments)
}
demo()
console.log(document.getElementsByTagName('div'));
console.log(document.querySelectorAll('div'));
// 遍历迭代器
// for (let item of arr) {
for (let item of document.getElementsByTagName('div')) {
console.log(item)
}
调用Iterator接口
- 数组的解构
// =======数组 解构执行了
let arr = [1,2,3];
arr[Symbol.iterator]= function(){
return {
next() {
console.log('iterator done')
return { value: 'hello', done: true }
}
}
}
let [a,b,c] = arr
//对象解构 不会执行
let obj = { num: 100 }
// 重写迭代器接口
obj[Symbol.iterator] = function() {
return {
next() {
console.log('iterator done')
return { value: 'hello', done: true }
}
}
}
let { num } = obj;
- 扩展运算符(三个点语法)
//三点语法
let arr = [1, 2, 3];
// let arr = new Set([4, 5, 6])
// let arr = new Map([[100, 200]])
// 默认没有迭代器方法
// let arr = new WeakSet([location])// 注意没有三个点语法
// let arr = { num: 200 }
// 重写迭代器接口
arr[Symbol.iterator] = function() {
return {
next() {
console.log('iterator done!!!')
return { value: 'hello', done: true }
}
}
}
console.log([...arr])
for...of
循环Array.from
方法
// 4 Array.from会执行参数对象的迭代器方法
// let divs = document.querySelectorAll('div');
// divs[Symbol.iterator] = function() {
// return {
// next() {
// console.log('iterator done!!!')
// return { value: 'hello', done: true }
// }
// }
// }
// console.log(Array.from(divs))
Map
,Set
,WeakMap
与WeakSet
参数
// map和set实现了迭代器接口,而WeakSet和WeakMap没有实现
console.log(Map.prototype[Symbol.iterator])
console.log(Set.prototype[Symbol.iterator])
console.log(WeakMap.prototype[Symbol.iterator])
console.log(WeakSet.prototype[Symbol.iterator])// 5 set map, weakset, weakmap
// let arr = [1, 2, 3];
// let arr = [[100, 200], ['color', 'red'], [2, 3]];
// let arr = [[location, 200]];
// // 重写迭代器接口
// arr[Symbol.iterator] = function() {
// return {
// next() {
// console.log('iterator done!!!')
// return { value: 'hello', done: true }
// }
// }
// }
// 创建set对象
// console.log(new Set(arr));
// console.log(new Map(arr));
// console.log(new WeakSet(arr));
// console.log(new WeakMap(arr));
Promise.all
与Promise.race
// let divs
let arr = [1, 2, 3];
arr[Symbol.iterator] = function() {
return {
next() {
console.log('iterator done!!!')
return { value: 'hello', done: true }
}
}
}
Promise.all(arr)
Promise.race(arr)
- 字符串对象解构
// 7 字符串对象解构
let str = new String('111')
str[Symbol.iterator] = function() {
return {
next() {
console.log('iterator done!!!')
return { value: 'hello', done: true }
}
}
}
console.log([...str])
generator
函数的yield
语句等
return
与throw
迭代器接口返回的对象中,除了必须定义next
方法外,还可以设置return
和throw
方法:
return
方法:当for...of
语句提前结束的时候会使用该方法。 如在for...of
语句中使用了break
或者continue
关键字throw
方法主要配合generator
函数使用。
// ========= return
let arr = [1,2,3,4,5,6,7,8]
arr[Symbol.iterator] = function(){
//缓存tis
let me = this;
return {
index:1,
next(){
this.index++;
if(this.index===me.length){
return {value:undefined,done:true}
}
return {value:me[this.index],done:false}
},
//终止方法
return(){
console.log("121212")
return {value:me[this.index],done:true}
}
}
}
//遍历
// for(let item of arr){
// if(item===3){
// break
// }
// }
ickt:for(let i = 0;i<3;i++){
for(let item of arr){
console.log(item)
if(item===3){
continue ickt;
}
}
}
for...of
循环 注意事项
- 遍历数组
- 只能遍历数字索引属性,不能遍历其它属性
let arr = [4,5,6,7,8] // 添加书香 arr.color = "red" //遍历 for(let item of arr){ console.log(item,"121") }
for
循环只能获取成员值,无法获取索引值(for...in
正好相反),可以借用keys
以及entries
解决
// ==== for of 注意事项 let arr = [4,5,6,7,8] // 添加书香 arr.color = "red" //遍历 for(let item of arr){ console.log(item,"121") } // keys values entries for(let item of arr.keys()){ console.log(item) } for(let item of arr.values()){ console.log(item) } for(let item of arr.entries()){ console.log(item) }
set
与map
对象- 遍历的顺序就是成员添加的顺序
set
返回的是成员值,map
返回的是包含索引值与成员值的数组。
keys
,values
以及entries
是专门为迭代器接口设计的方法,因此for...of
循环可以遍历这些方法返回的数据
let set = new Set();
set
.add('color')
.add('red')
.add('green')
for (let item of set) {
console.log(item)//// 返回键值
}
// 没有键名,只有键值
for (let item of set.entries()) {
console.log(item)// 返回键值对
}
let map1 = new Map()
map1
.set('color', 'red')
.set('num', 100)
.set('green', 'blue')
for (let item of map1) {
console.log(item) // 返回键值对
}
console.log(Set.prototype[Symbol.iterator] === Set.prototype.values)
console.log(Map.prototype[Symbol.iterator] === Map.prototype.entries)
for...of
循环还可以遍历字符串,类数组对象(实现了迭代器接口的)。
// 遍历类数组和字符串
let str = 'ickt';
for (let item of str) {
console.log(item)
}
// 遍历类数组
function demo() {
for (let item of arguments) {
console.log(item)
}
}
demo(1, 2, 3, 4, 5)
对于未实现迭代器接口的类数组对象可以使用Array.from
方法转化
// 没有实现迭代器接口
let arrLike = {
0: 'red',
1: 'green',
2: 'blue',
length: 3
}
// 没有实现迭代器接口的对象,无法遍历,为了遍历可以使用Array.from方法转化。
for (let item of Array.from(arrLike)) {
console.log(item)
}
for...of
循环可以遍历实现迭代器接口的对象。没有实现迭代器接口的对象我们可以使用Object.keys
、values
、entries
等方法转化,也可以使用generator
方法处理
// 对象
let obj = {
color: 'red',
msg: 'hello',
num: 100
}
// for (let item of obj) {
// console.log(item)
// }
// 转成数组
// for (let item of Object.keys(obj)) {
// console.log(item)
// }
// for (let item of Object.values(obj)) {
// console.log(item)
// }
// for (let item of Object.entries(obj)) {
// console.log(item)
// }
// generator
// function *demo() {
// yield 1;
// yield 2;
// yield 3;
// }
// 将属性键值对定义成状态
function *demo(obj) {
// 遍历对象属性名称
for (let key in obj) {
yield [key, obj[key]]
}
}
let d = demo(obj);
// console.log(d.next())
// console.log(d.next())
// console.log(d.next())
// console.log(d.next())
for (let item of d) {
console.log(item)
}
来源:oschina
链接:https://my.oschina.net/u/4162046/blog/3218074