常见循环: for循环、forEach循环、for in循环
for循环
缺点: i变量层级太深不好理解,不够语义化
let colors = ['red', 'yellow', 'blue'];
for(let i = 0; i < colors.length; i++){
if(colors[i] === 'yellow'){
break // 可以跳出循环
}
// console.log(colors[i])
}
forEach循环
缺点: 跳不出循环
let colors = ['red', 'yellow', 'blue'];
colors.forEach((item, index, arr) => console.log(item) )
for in 循环
缺点: 新增属性也会被循环
let colors = ['red', 'yellow', 'blue'];
colors.name = 'black'
for(let i in colors){
console.log(colors[i])
}
迭代器
定义: 在迭代器函数中传入数组,调用.next()方法会返回一个对象。对象中包含value和done,value等所在循环次数中的值,循环完返回undefined;done返回false,循环完返回true。
手写迭代器
//手写迭代器
function createIterator(arr) {
var index = 0;
return {
next() {
return index < arr.length ?{value: arr[index++],done: false} : {value: undefined,done: true}
// 一样
// return index < arr.length ?{value: arr[index],done: false, index: index++} : {value: undefined,done: true}
}
}
}
let colors = ['red', 'yellow', 'blue'];
let iterator = createIterator(colors);
iterator.next() // {value: 'red', done: false}
iterator.next() // {value: 'yellow', done: false}
iterator.next() // {value: 'blue', done: false}
iterator.next() // {value: 'undefined', done: true}
默认迭代器: 存储在Symbol属性中
let colors = ['red', 'yellow', 'blue'];
console.log( colors[Symbol.iterator] ) // 返回一个函数
let arrIt = colors[Symbol.iterator]() // 执行函数变成迭代器
console.log( arrIt.next() ) // {value: 'red', done: false}
类数组迭代器
<p>lzl</p>
<p>yc</p>
<p>zlm</p>
<p>llh</p>
<script>
let argIt;
function fn(){
argIt = arguments[Symbol.iterator]()
}
fn(1,2,3)
console.log(argIt.next()) // {value: 1, done: false}
let myP = document.getElementsByTagName('p');
console.log(myP) // 返回HTML集合
console.log( myP[Symbol.iterator] ) // 返回一个函数
console.log( myP[Symbol.iterator]() ) // 返回迭代器
let pIt = myP[Symbol.iterator]() // 可以迭代
console.log(pIt.next()) // {value: p, done: false}
</srcipt>
字符串迭代
let str = 'fanghuayong'
console.log(str[Symbol.iterator]()) // 返回迭代器
let strIt = str[Symbol.iterator]() // 可以迭代
对象可以迭代吗? 答:不可以
let obj = { a: 1 }
console.log(obj[Symbol.iterator]) //返回undefined 对象没有迭代器
迭代器使用场景
for of循环
优点: 底层使用迭代器 直接循环变量 可以中途跳出 语羽化
<p>lzl</p>
<p>yc</p>
<p>zlm</p>
<p>llh</p>
<script>
let colors = ['red', 'yellow', 'blue'];
for(let color of colors){
console.log('循环中')
if(color == 'yellow'){
break // 可以跳出循环
}
// console.log(color)
}
let argIt;
function fn(){
// argIt = arguments[Symbol.iterator]();
for(let argument of arguments){
console.log(argument) // 可以直接打印元素
}
}
fn(1,2,3)
let myP = document.getElementsByTagName('p');
// console.log(myP) // 返回HTML集合
for(let p of myP){
console.log(p) // 返回dom节点
}
</script>
数组新增方法
let colors = ['red', 'yellow', 'blue'];
console.log(colors.keys()) // 返回迭代器
for(let color of colors.keys()){
console.log(color) // 迭代索引
}
for(let color of colors.values()){
console.log(color) // 迭代值
}
for(let color of colors.entries()){
console.log(color) // 以数组形式迭代索引和值 [0, "red"]
}
解构赋值
let colors = ['red', 'yellow', 'blue'];
// [index, color] = [0, 'red']
for(let [index, color] of colors.entries()){ // 用数组作为迭代单位
console.log(index, color) // 直接解构赋值
}
...运算符: 底层是用迭代器实现的
let colors = ['red', 'yellow', 'blue'];
let colors1 = ['black', ...colors] // ...运算符的底层是用迭代器实现的
console.log(colors1) // 返回 ["black", "red", "yellow", "blue"]