JS 中常用的循环
for 循环、while 循环、Array.prototype.forEach 可以迭代数组
for of 循环 「扩充:for await of」 for in 循环
性能从高到低:
「for 循环(i 是有的) -> for 循环(i 是全局的) && while 循环」-> forEach 循环(内部封装的方法,肯定做了一些逻辑判断处理,所以要稍微比命令式编程慢一些) -> for/of 循环 -> for/in 循环(它会依次查找私有和原型链上所有可枚举的属性,所以比其他循环慢很多,项目中不建议使用 for/in)
//测试性能
let arr = new Array(9999999).fill(null);
console.time('FOR');
for (var i = 0; i < arr.length; i++) { }
console.timeEnd('FOR');
console.time('FOR2');
let m = 0;
for (; m < arr.length; m++) { }
console.timeEnd('FOR2');
console.time('WHILE');
let k = 0;
while (k < arr.length) { k++; }
console.timeEnd('WHILE');
console.time('FOREACH');
arr.forEach(() => { });
console.timeEnd('FOREACH');
console.time('FOROF');
for (let value of arr) { }
console.timeEnd('FOROF');
console.time('FORIN');
for (let key in arr) { }
console.timeEnd('FORIN');
for
for 有三个表达式:① 声明循环变量;② 判断循环条件;③ 更新循环变量;
三个表达式之间,用";"分割,for 循环三个表达式都可以省略,但是两个";"缺一不可。
for 循环的执行特点:先判断再执行,与 while 相同 for 循环三个表达式都可以有多部分组成,第二部分多个判断条件用&&(并) ||(或)连接,第一三部分用逗号分割; for 循环更适用于循环的开始和结束已知,循环次数固定的场合;
for 循环语法:for(变量=开始值;变量<=结束值;变量=变量+步进值){循环语句}
//for循环 实例:
let arr=[1,2,3,4,5];
for(let i=0;i<arr.length;i++){
if(i==1){
continue
}
console.log(arr[i]);
}
while
简介:
While 循环会在指定条件为真时循环执行代码块;
使用 break 语句来跳出循环,使用continue 语句用于跳出当前的迭代,并开始下一次迭代。
语法:while(判断条件){执行代码}
//求1+2+···+100的和
var n1=1;
var sum=0;
while(n1>=1 && n1<=100){
sum=sum+n1;
n1++;
}
console.log(sum); //输入为5050
//当等于3跳出循环
var text = "";
var i = 0;
while (i < 5) {
text += "<br>The number is " + i;
i++;
if (i == 3) {
break;
}
console.log(i) // 1 2
}
console.log(i) // 3
//当等于3时跳过 该循环
var text = "";
var i = 0;
while (i < 5) {
i++;
if (i == 3) {
continue;
}
text= i;
console.log(text) // 1 2 4 5
}
do...while
简介:
do/while 循环是 while 循环的变体。该循环会执行一次代码块,在检查条件是否为真之前,然后如果条件为真的话,就会重复这个循环。
语法:do{需要执行的代码}while (条件);
// 求1到100之间的数字和
var n1=1;
var sum=0;
do{
sum=sum+n1;
n1++;
}
while (n1>=1 && n1<=100)
console.log(sum)
forEach
简介:
forEach:用来遍历数组中的每一项;这个方法执行是没有返回值的,对原来数组也没有影响;
无法使用break等语句跳出遍历, 直到所有元素都传递给调用的函数, 但是可以使用抛出异常, 提前终止循环
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
语法: array.forEach(function(currentValue, index, currentArray){ } , thisValue);
- currentValue为数组当前item的一个副本,因此改变currentValue不会对原数组产生影响 可以通过currentArray与index改变原数组
- forEach 是声明式(不关心如何实现),没办法使用 break 语句跳出循环,或者使用 return 从函数体内返回。
let sum = 0
var arr = [1,2,3,4];
arr.forEach(function(value,index,array){
// array[index] == value; //结果为true
sum+=value;
console.log(index,value)
//输出结果是 0 1
// 1 2
// 2 3
// 3 4
console.log(array) // [1,2,3,4]
});
console.log(sum); //结果为 10
map
简介:
- map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理的后值。
- map()方法按照原始数组元素顺序依次处理元素。
- size() 获取Map元素个数
- isEmpty() 判断Map是否为空
- clear() 删除Map所有元素
- put(key, value) 向Map中增加元素(key, value)
- remove(key) 删除指定key的元素,成功返回true,失败返回false
- get(key) 获取指定key的元素值value,失败返回null
- element(index) 获取指定索引的元素(使用element.key,element.value获取key和value),失败返回null
- containsKey(key) 判断Map中是否含有指定key的元素
- containsValue(value) 判断Map中是否含有指定value的元素
- keys() 获取Map中所有key的数组(array)
- values() 获取Map中所有value的数组(array)
- 语法:array.map(function(当前元素的值,索引,数组), 执行函数)
var users = [
{name: "熊大", "email": "zhang@email.com"},
{name: "熊二", "email": "jiang@email.com"},
{name: "光头强", "email": "jiang@email.com"}
];
// emails => email的数组
var emails = users.map(function (user) { return user.email; });
console.log(emails) // [zhang@email.com,jiang@email.com,jiang@email.com]
for...in
for-in 循环用于遍历一个集合里面的所有元素,例如由数字表示的区间、数组中的元素、字符串中的字符。
for in这种循环i是string类型的
作用于数组的for-in循环体除了遍历数组元素外,还会自身可枚举属性
如果给对象的原型加上方法,for in这种循环会把数组原型链上的属性都能被访问到。
在某些情况下,这段代码可能按照随机顺序遍历数组元素。 简而言之,for-in是为普通对象设计的,你可以遍历得到字符串类型的键,因此不适用于数组遍历。
注:json只能用for in循环,因为json的下标是没有规律的字符串,没有length。
for...in语法:for(变量 in 对象){执行语句}
//循环数组
let arr=[1,2,3,4,5];
for(let key in arr){
console.log(key);
}
//循环对象
var obj = {
w: "wen",
j: "jian",
b: "bao"
}
for(var v in obj){
console.log(obj[v]) //输出为 wen jian bao
console.log(v) // 输出为 w j b
}
for..of
简介:
推荐在循环对象属性的时候,使用for...in,在遍历数组的时候的时候使用for...of。
for...in循环出的是key,for...of循环出的是value
注意,for...of是ES6新引入的特性。修复了ES5引入的for...in的不足
for...of不能循环普通的对象,需要通过和Object.keys(),Object.values,Object.entries配使用 for..of 语法:for( 自定义一个值 of 数组 ){执行语句}
//循环数组
let arr=[1,2,3,4,5];
for(let val of arr){
console.log(val);
}
//循环对象
var arr = [ { name:'nick', age:18 }, { name:'freddy', age:24 }, { name:'mike', age:26 },];
for(var x of arr) {
console.log(x.name, item.age);
//输出为 nick,18
// freddy,24
// mike, 26
}
//for in
for(var x of arr) {
console.log(x.name, x.age);//报错 x在这里指的是key值 name
let obj={name:"lili",age:28};
//缺点: 原型上的属性,也给循环了
for(key in obj){
console.log(obj[key]);
}
for(value of Object.keys(obj)){
console.log(value);
}
for(value of Object.values(obj)){
console.log(value);
}
for(let [key,value] of Object.entries(obj)){
console.log(key,value);
}
}
支持 return,并且是值 of 数组(不能遍历对象)
- 可以避免所有 for-in 循环的陷阱
- 不同于 forEach(),可以使用 break, continue 和 return
- for-of 循环不仅仅支持数组的遍历。同样适用于很多类似数组的对象
- 它也支持字符串的遍历
- for-of 并不适用于处理原有的原生对象
把 Symbol.iterator 方法执行,会返回一个具备迭代器规范的 itor 对象,基于 itor.next()依次执行,就可以获取到数据集合中的每一项!! ES6 中新提供的“for...of”循环,就是按照这套机制去迭代的!
Object.prototype 上不具备 Symbol.iterator,一个普通对象默认不能基于迭代器规范循环,也就是不能使用 for...of
Iterator 迭代器:只是一种机制,可以为各种不同的数据结构提供统一的循环和迭代规范,而 for of 循环本身就是基于这种进制进行迭代的!
- 拥有 Iterator 机制的对象,必须具备 next 方法:执行这个方法可以依次访问对象中的每个成员
- 执行 next 返回值是一个对象:
- value:当前迭代的这一项
- done:记录是否迭代完成
虽然不具备 Iterator 内置类,但是对于某些数据结构,它提供了 Symbol.iterator 属性方法,这个方法具备迭代器规范,基于这个方法可以依次迭代数据中的每一项
- 数组 Array.prototype[Symbol.iterator]=function...
- Set.prototype / Map.prototype
- String.prototype
- NodeList.prototype
- arguments[Symbol.iterator]
- generator object