ES6基础之解构、数组与对象遍历汇总

709 阅读5分钟

一.解构

1.数组的解构

// 基础类型解构
let [a,b,c] = [1,2,3];
console.log(a,b,c); // 1,2,3

// 数组对象解构
let [a,b,c] = [{name: 1},{name: 2}, {name: 3}];
console.log(a,b,c); // {name: 1},{name: 2}, {name: 3}

// ...解构
let [head,...tail] = [1,2,3,4];
console.log(head,tail);// 1, [2,3,4]

// 嵌套解构
let [a,[b],c] = [1,[2,3], 4];
console.log(a,b,c);// 1,2,4

// 解构不成功为undefined
let [a,b,c] = [1];
console.log(a,b,c);// 1, undefined ,undefined

// 解构默认赋值
let [a=1,b=2] = [3];
console.log(a,b);// 3, 2

2.对象的解构

//对象属性解构
let {f1,f2} = {f1:'test1',f2:'test2'};
console.log(f1,f2);// test1,test2

// 可以不按照顺序,这是与数组解构与数组解构区别之一
let {f1,f2} = {f1:'test',f2:'test2'};
console.log(f1,f2);// test1,test2 

// 解构对象命名
let {f1:rename,f2} = {f1:'test1',f2:'test2'};
console.log(rename,f2);// test1, test2

//嵌套解构
let {f1: {f11}} = {f1:{f11:'test11',f2:'test12'}}
console.log(f11);//test11

// 默认值
let {f1='test1',f2:rename = 'test2'} = {f1:'current1',f2:'current2'};
console.log(f1,rename);// current1,current2

3.解构的原理是什么?

  • 针对可以迭代对象的Iterator,通过遍历器按顺序获取对应的值进行赋值.
3.1 Interator是什么?
  • Interator 是一种接口,为各种不一样的数据解构提供统一的访问机制,任何数据解构只要有interator接口,就能通过遍历操作,一次按顺序处理数据结构内所有成员,es6中的for of 的语句相当于遍历器,会在遍历数据结构的时候,自动寻找Iterator接口.
3.2 Interator 的作用
  • 为各种数据解构提供统一的访问接口
  • 使得数据解构能按次序排列处理
  • 可以使用ES6最新命令 for of进行遍历
function generateIterator(array) {
    let index = 0;
    return {
        next: () => index < array.length ? {
            value: array[index++],
            done: false
        } : {
            value: undefined,
            done: true
        }
    
    };

}

const iterator = generateIterator([1,2,3]);

console.log(interator.next()); // 1
console.log(interator.next()); // 2
console.log(interator.next()); // 3
console.log(interator.next()); // undefined
3.3 可迭代对象
  • 可以迭代对象是Iterator接口的实现,这是ECMAScript 2015的补充,他不是内置或语法,而仅仅是协议,任何遵循改协议都能成为可迭代对象,可迭代对象得有2个协议,可以迭代协议和迭代器协议.

  • 可迭代协议: 对象必须实现Iterator方法,即对象或其原型链上必须有一个名叫Symbol.iterator的属性,该属性的值为无参函数,函数返回迭代器协议.

  • 迭代器协议:定义了标准的方式来产生一个有限或无限序列值,其要求必须实现一个next()方法,该方法返回对象done(boolean)和value属性.

3.4 实现一个for of 遍历的对象
  • 自定义数据解构,只要拥有Iterator接口,并将其部署到自己的Symbol.iterator属性上,就可以成为可迭代对象,能被for of循环遍历.
const obj = {
    count: 0,
    [Symbol.iterator]: () = {
        return {
            next: () => {
                obj++;
                if(obj.count <= 10) {
                    return {
                        value: obj.count,
                        done: false
                    }
                
                } else {
                    return {
                        value: undefined,
                        done: true
                    }
                }
            
            }
        
        }
    
    }

};

for (const item of obj) {
    console.log(item);
}


//或者
const iterable = {
    0:'a',
    1:'b',
    2:'c',
    length: 3,
    [Symbol.iterator]:Array.prototype[Symbol.iterator]

};

for (const item of iterable) {
    console.log(item);
}

二 .遍历

1.数组遍历

1.1 for、forEach、 for of
const list = [1,2,3,4,5,6,7,8];

// for
for (let i = 0; len = list.length; i< len; i++) {
    if(list[i] === 5) {
        break; // 1,2,3,4
        // continue; // 1,2,3,4,6,7,8
    }
    console.log(list[i]);
}

// forEach
const list = [1,2,3,4,5,6,7,8];
list.forEach((item,index,arr) => {
    if (item === 5) return;
    console.log(index); // 0 1 2 3 4 6 7 8
    console.log(item); //  1 2 3 4 6 7 8
});

for (const item of list) {
    if (item === 5) {
        break; //  1 2 3 4
        // continue; // 1 2 3 4 6 7 8
    }
}
  • 总结:
  1. 三个都是从左往右遍历数组

  2. forEach 无法跳出循环,for和for of 可以使用break或者continue中断

  3. for of 直接访问的是实际元素,for遍历数组索引,forEach回调函数参数更丰富, 元素、索引、原数组都可以直接获取

  4. for of与for 如果数组中存在空的元素,同样会执行

1.2 filter、map
//filter
const list = [
{id: 1, name: '小一', age: 11},,
{id: 2, name: '小二', age: 12},
{id: 3, name: '小三', age: 13}
];

const reslist = list.filter(item => item.age === 11);
console.log(reslist); // {id: 1, name: '小一', age: 11}

// map 
const newlist = list.map(item => item.id);
console.log(newlist); // [1,2,3]

  • 总结:
  1. 二个都会生成一个新的数组,不会改变原来数组

  2. 二个都会跳过空的元素

  3. map会将回调函数的返回值组成一个新的数组,长度和原来数组一致

  4. filter 会将回调函数条件的元素组成一个新的数组,长度与原来的不一致

  5. map生成的新数组元素可以自定义

6.filter生成的数组元素不能自定义,与原来数组元素一致

1.3 some 、every
// some
const list = [1,2,3,4,5,6];
const newlist = list.some(item => item > 5);
console.log(newlist); // true

const everyList = list.every(item => item > 5);
console.log(newlist); // false

总结:

  • 2个都是用来做数组判断用的,都是返回一个布尔值,
  • some:若数组中有一个元素满足条件都返回true,循环中断,所有元素不满足,则返回false
  • every: 和some刚好相反,若是数组中有一个元素不满足条件,则返回false,循环中断,若是所有元素都满足,则返回true;
1.4 find、findIndex
const list = [
{id: 1, name: '小一', age: 11},
{id: 2, name: '小二', age: 12},
{id: 3, name: '小三', age: 13}
];
const result = list.find(item => item.id === 3);
console.log(result);// { id: 3, name: '小三', age: 13 }

const index = list.findIndex(item => item.id === 3);
console.log(index); // 2

总结:

  • find方法返回数组中满足callback函数的第一个元素的值,如果不存在返回undefined
  • find 方法返回数组中所查找元素的下标,如果不存在返回-1;
  • 2个都是用来查找数组元素
1.5 reduce、reduceRight
  • reduce方法接收2个参数,第一个参数是回调函数(callback),第二个参数是初始值(initialValue);
// 计算对象数组中某一属性的总和
const list = [
{id: 1, name: '小一', age: 11},
{id: 2, name: '小二', age: 12},
{id: 3, name: '小三', age: 13}
];
const sum = list.reduce((a, item) => {
    return a + item.id;
},0);
console.log(sum); // 6
  • reduceRight方法也是接收2个参数,第一个参数是回调函数(callback),第二个参数是初始值(initialValue); array.reduceRight(function(total, currentValue, currentIndex, arr), initialValue)
  1. total 初始值,计算结束后的返回值
  2. currentValue 当前元素
  3. currendIndex 当前元素索引
  4. arr 当前元素所属的数组对象
// 计算数组中元素的总和
let arr = [0,1,2,3,4];
const result = arr.reduceRight((total,item,index,arr) => {
    return total + item;
},0);
console.log(result); // 10

2.对象遍历

2.1 for in
  • 遍历数组时,key为数组下标字符串,遍历对象,key为对象字段名
let obj = {a: 'test1', b: 'test2'};
for (let key in obj) {
    console.log(key,obj(key)); 
    //a test1
    // b test2
}

缺点: 1.for in 不仅会遍历当前对象,还包括原型链上的可枚举属性 2.for in 不适合遍历数组,主要应用于对象

2.2 Object.keys
  • 改方法返回一个给定对象的自身可枚举属性组成的数组
const obj = {a:1,b:2};
const keys = Object.keys(obj);// [a,b]

// 手动模拟Object.keys实现

function getObjectKeys(obj) {
    const result = [];
    for (const prop in obj) {
        if(obj.hasOwnProperty(prop)) {
            result.push(prop);
        }
    }
    return result;

}
2.3 Object.values
  • 该方法返回一个给定对象自身的所有可枚举属性值的数组
const obj = {a:1,b:2};
const keys = Object.values(obj);// [1,2]

// 手动模拟Object.values实现

function getObjectValues(obj) {
    const result = [];
    for (const prop in obj) {
        if(obj.hasOwnProperty(prop)) {
            result.push(obj[prop]);
        }
    }
    return result;

}
2.4 Object.entries
  • 该方法返回一个给定对象自身可枚举属性的键值对数组
const obj = {a:1,b:2};
const keys = Object.entries(obj);// [[‘a’,1],[‘b’,2]]

// 手动模拟Object.values实现

function getObjectEntries(obj) {
    const result = [];
    for (const prop in obj) {
        if(obj.hasOwnProperty(prop)) {
            result.push(prop,obj[prop]);
        }
    }
    return result;

}
2.5 Object.getOwnPropertyNames
  • 该方法返回一个数组,该数组对元素是obj自身拥有的枚举或不可枚举属性名称字符串.
Object.prototype.aa = '1111';
const testData = {a: 1,b: 2 }
for (const key in testData) {
    console.log(key);
}
     console.log(Object.getOwnPropertyNames(testData));
//a
// b
// aa
// [ 'a', 'b' ]