以前for循环,for in循环;而es6新增循环:for of 循环:遍历(迭代,循环)整个对象。
for..of
es6新增了一个for..of
循环,在迭代器生产的一系列值的循环。for..of
循环的值必须是一个iterable
。
var a = ["a", "b","c","d","e"]
for(var idx in a){
console.log(idx)
}
// 0 1 2 3 4
for(var val of a){
console.log(val)
}
// a b c d e
for..in
在数组a
的键/索引上循环,for..of
在a
的值上循环。
es6
之前的代码
var a = ["a", "b","c","d","e"]
for(var val, ret, it = a[symbol.iterator]();(ret=it.next()) && !ret.done){
val = ret.value
console.log(val)
}
// a b c d e
在底层,
for..of
循环向iterable请求一个迭代器,然后反复调用这个迭代器把它产生的值赋给循环迭代变量。
javascript
默认为iterable的标准内建值包括:
array
strings
generators
collections/typedarrays
字符串迭代方式
for(var c of "hello"){
console.log(c)
}
// h e l l o
原生字符串值被强制类型转换到等价的string封装对象中,它是一个iterable
for(xyz of abc)
对于xyz
这个位置既可以是赋值表达式,也可以是声明。下面看个赋值表达式的例子:
var o = {}
for(o.a of [1,2,3]){
console.log(o.a)
}
o // {a:3}
for({x:o.a} of [{x:1},{x:2},{x:3}]){
console.log(o.a)
}
o // {a:3}
通过break
,continue
,return
提前终止循环。
自定义迭代器
通过对底层的了解,for..of
向iterable
请求一个迭代器,然后反复调用这个迭代器把它产生的值赋给循环迭代变量。那么我可以自定义一个iterable
。
var o = {
[symbol.iterator](){
return this
},
next(){
if(!val){
val = 1
}else{
val
}
return {value:val, done:val== 6}
}
}
for(var val of o[symbol.iterator]()){
console.log(val)
}
由此可见,自定义迭代器满足两个条件,[symbol.iterator]
属性,返回的对象中有next
方法,next
方法返回值必须是{value:xx,done:xx}
的形式,如果遇到done:true
,则循环结束。
结语:以上就是for..of循环的全部内容,它可以循环可迭代对象。
扩展知识:为什么要引进 for-of?
要回答这个问题,我们先来看看es6之前的 3 种 for 循环有什么缺陷:
- foreach 不能 break 和 return;
- for-in 缺点更加明显,它不仅遍历数组中的元素,还会遍历自定义的属性,甚至原型链上的属性都被访问到。而且,遍历数组元素的顺序可能是随机的。
所以,鉴于以上种种缺陷,我们需要改进原先的 for 循环。但 es6 不会破坏你已经写好的 js 代码。目前,成千上万的 web 网站依赖 for-in 循环,其中一些网站甚至将其用于数组遍历。如果想通过修正 for-in 循环增加数组遍历支持会让这一切变得更加混乱,因此,标准委员会在 es6 中增加了一种新的循环语法来解决目前的问题,即 for-of 。
那 for-of 到底可以干什么呢?
- 跟 foreach 相比,可以正确响应 break, continue, return。
- for-of 循环不仅支持数组,还支持大多数类数组对象,例如 dom nodelist 对象。
- for-of 循环也支持字符串遍历,它将字符串视为一系列 unicode 字符来进行遍历。
- for-of 也支持 map 和 set (两者均为 es6 中新增的类型)对象遍历。
总结一下,for-of 循环有以下几个特征:
- 这是最简洁、最直接的遍历数组元素的语法。
- 这个方法避开了 for-in 循环的所有缺陷。
- 与 foreach 不同的是,它可以正确响应 break、continue 和 return 语句。
- 其不仅可以遍历数组,还可以遍历类数组对象和其他可迭代对象。
但需要注意的是,for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用
for-in 循环(这也是它的本职工作)。
最后要说的是,es6 引进的另一个方式也能实现遍历数组的值,那就是 iterator。上个例子:
const arr = ['a', 'b', 'c'];
const iter = arr[symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
前面的不多说,重点描述for-of
for-of循环不仅支持数组,还支持大多数类数组对象,例如dom nodelist对象。
for-of循环也支持字符串遍历,它将字符串视为一系列的unicode字符来进行遍历:
window.onload=function(){
const arr = [55,00, 11, 22];
arr.name = "hello";
// array.prototype.fathername = 'fathername';
/*for(let key in arr){
console.log('key=' key ',key.value=' arr[key]);
}*/
/* arr.foreach((data) => {console.log(data);});*/
/* arr.foreach((data,index,arr) => {console.log(data ',' index ',' arr);});*/
/*for(let key of arr){
console.log(key);
}*/
var string1 = 'abcdefghijklmn';
var string2 = 'opqrstuvwxyc';
const stringarr = [string1,string2];
for(let key of stringarr){
console.log(key);
}
for(let key of string1){
console.log(key);
}
}
结果:
现在,只需记住:
- 这是最简洁、最直接的遍历数组元素的语法
- 这个方法避开了for-in循环的所有缺陷
- 与foreach()不同的是,它可以正确响应break、continue和return语句
for-in循环用来遍历对象属性。
for-of循环用来遍历数据—例如数组中的值。
它同样支持map和set对象遍历。
map和set对象是es6中新增的类型。es6中的map和set和java中并无太大出入。
set
和map
类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set
中,没有重复的key。
要创建一个set
,需要提供一个array
作为输入,或者直接创建一个空set
:
var s1 = new set(); // 空set
var s2 = new set([1, 2, 3]); // 含1, 2, 3
重复元素在set中自动被过滤:
var s = new set([1, 2, 3, 3, '3']);
console.log(s); // set {1, 2, 3, "3"}
通过add(key)
方法可以添加元素到set
中,可以重复添加,但不会有效果:
var s = new set([1, 2, 3]);
s.add(4);
s; // set {1, 2, 3, 4}
s.add(4);
s; // set {1, 2, 3, 4}
通过delete(key)
方法可以删除元素:
var s = new set([1, 2, 3]);
s; // set {1, 2, 3}
s.delete(3);
s; // set {1, 2}
set对象可以自动排除重复项
var string1 = 'abcdefghijklmn';
var string2 = 'opqrstuvwxyc';
var string3 = 'opqrstuvwxyc';
var string4 = 'opqrstuvwxyz';
const stringarr = [string1,string2,string3,string4];
var newset = new set(stringarr);
for(let key of newset){
console.log(key);
}
结果:
map对象稍有不同:内含的数据由键值对组成,所以你需要使用解构(destructuring)来将键值对拆解为两个独立的变量:
for (var [key, value] of phonebookmap) {
console.log(key "'s phone number is: " value);
}
示例
var m = new map([[1, 'michael'], [2, 'bob'], [3, 'tracy']]);
var map = new map([['1','jckey'],['2','mike'],['3','zhengxin']]);
map.set('4','adam');//添加key-value
map.set('5','tom');
map.set('6','jerry');
console.log(map.get('6'));
map.delete('6');
console.log(map.get('6'));
for(var [key,value] of map) {
console.log('key=' key ' , value=' value);
}
结果: