ES6-遍历数组

数组是一种很重要的数据结构。那么我们如何遍历数组呢?
我们如何遍历数组中的元素?20年前JavaScript刚萌生时,你可能这样实现数组遍历:

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

自ES5正式发布后,你可以使用内建的forEach方法来遍历数组:

myArray.forEach(function (value,index) {
console.log(index+":"+value);
});

这段代码看起来更加简洁,但这种方法也有一个小缺陷:你不能使用break语句中断循环,也不能使用return语句返回到外层函数。另外,forEach方法是Array对象的方法,所以对于DOM的类数组,如NodeList对象,则不能遍历。

当然,如果只用for循环的语法来遍历数组元素也很不错。
那么,你一定想尝试一下for-in循环:

for (var index in myArray) { // 千万别这样做
  console.log(myArray[index]);
}

这绝对是一个糟糕的选择,为什么呢?

  • 在这段代码中,赋给index的值不是实际的数字,而是字符串“0”、“1”、“2”,此时很可能在无意之间进行字符串算数计算,例如:“2” + 1 == “21”,这给编码过程带来极大的不便。
  • 作用于数组的for-in循环体除了遍历数组元素外,还会遍历自定义属性。举个例子,如果你的数组中有一个可枚举属性myArray.name,循环将额外执行一次,遍历到名为“name”的索引。就连数组原型链上的属性都能被访问到。
  • 最让人震惊的是,在某些情况下,这段代码可能按照随机顺序遍历数组元素
  • 简而言之,for-in是为普通对象设计的,你可以遍历得到字符串类型的键,因此不适用于数组遍历

强大的for-of循环

每个具有遍历器方法的对象都称为”可遍历”对象。
for of遍历一种数据集合时,首先会寻找这个集合是否有遍历器方法,没有就抛出错误,有就调用这个方法。遍历器方法返回一个遍历对象,遍历对象的根本特征就是具有next方法。每次调用next方法,都会返回一个代表当前成员的信息对象,具有value和done两个属性。

for of就是不断调用next方法来遍历的
ES6规定,遍历器方法保存在对象的[Symbol.iterator]属性中(这个属性的名字是内置的Symbol值,防止重名)

let obj = {
    a:1,
    b:2
};
console.log(obj[Symbol.iterator]); //undefined
for(let x of obj){
    console.log(x);   
}
// Uncaught TypeError: obj is not iterable

对象没有默认的iterator接口([Symbol.iterator]),所以用for of遍历时就抛出了错误。
我们来给这个对象定义一个[Symbol.iterator]属性。

obj[Symbol.iterator]=function(){
    return {
        next: function(){
            return { value:1, done:false }
        }
    };
}
for(let x of obj){
    console.log(x);
}

有了遍历器方法后,for of就能遍历这个对象了,不过done属性为false,这个遍历就永远不会结束,它会一直打印1。

对象(Object)之所以没有默认部署Iterator接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。不过,严格地说,对象部署遍历器接口并不是很必要,因为这时对象实际上被当作Map结构使用,ES5没有Map结构,而ES6原生提供了。

具有[Symbol.iterator]属性的对象有:数组、某些类似数组的对象、Set和Map结构。我们可以自己定义对象的[Symbol.iterator]属性来覆盖默认的[Symbol.iterator]属性

let arr=[1,2,3];
arr[Symbol.iterator]=function(){
    let index=0;
    return {
        next:function(){
            if(index<arr.length){
                index++;
                return {
                    value:1,
                    done:false  
                }
            }else{
                return {
                    value:"遍历结束",
                    done:true
                }
            }
        }
    }
};
 //模拟for of循环
let iterator = arr[Symbol.iterator]();
iterator.next();    // {value: 1, done: false}
iterator.next();    // {value: 1, done: false}  
iterator.next();    // {value: 1, done: false}
iterator.next();    // {value: "遍历结束", done: true}

for(let x of arr){
    console.log(x);  // 1 1 1
}

ES6数组遍历方法

ES6给数组原型添加了几种新的遍历数组方法:Array.prototype.entries() Array.prototype.keys()和Array.prototype.values()(浏览器支持不好)

for…of循环内部调用的是数据结构的Symbol.iterator方法来遍历。
Array.prototype.entries() Array.prototype.keys()和Array.prototype.values()这些方法返回一个新的Symbol.iterator方法,for of内部调用的就是新迭代对象

Array.prototype.entries()
作用:遍历数组的键值对
参数:无
返回值:返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对

var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator);  // Array Iterator {}
console.log(iterator.next());   // {value: [0, "a"], done:false}
console.log(iterator.next()); // {value: [0, "a"], done:false}
console.log(iterator.next()); // {value: [0, "a"], done:false}

var iterator2 = arr.keys();
console.log(iterator);  // Array Iterator {}
console.log(iterator.next());   // {value: 0, done: false}
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
//数组默认的遍历器对象
for(let x of arr[Symbol.iterator]()){
        console.log(x);
}

// for of调用arr.keys()返回的遍历对象
for(let x of arr.keys()){
    console.log(x);
}

// for of调用arr.entries()返回的遍历对象
for(let [index,value] of arr.entries()){
    console.log(index,value);
}

console.log(arr.keys()===arr.entries());  //false

arr.entries()返回新的遍历对象,它包含了数组每个索引的键值对
arr.keys()返回新的遍历对象,它包含数组中每个索引的键



扩展运算符(…)也可以将某些数据结构转为数组。

[...[1,2,3]]    //[1,2,3]
[...document.querySelectorAll('div')] // NodeList对象转换为Array实例

扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。扩展运算符调用对象的遍历器方法,进行遍历。

let arr2=['a','b','c'];
var iterator=arr2.entries();
console.log([...iterator]);

图片

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值