ES6部分数组方法梳理

494 阅读6分钟

一.数组创建

1、Array.from()方法

Array.from 方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

let arrayLike = {
  "0": "a",
  "1": "b",
  "2": "c",
  length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
//任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换。
//扩展运算符只能对部署 Iterator 接口的类数组转换为真正的数组
//console.log([...arrayLike]); // 报错 TypeError: Cannot spread non-iterable object

//Array.from还可以接受第二个参数,作用类似于数组的map方法
var map = Array.from(arrayLike, x => x + x);
console.log(map); //  ["aa", "bb", "cc"]


2、Array.of()方法

Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。即Array.of 方法用于将一组值,转换为数组。弥补数组构造函数 Array()的不足。因为参数个数的不同,会导致 Array()的行为有差异

//如下代码看出差异
Array.of(3); // [3]
Array.of(3, 11, 8); // [3,11,8]

new Array(3); // [, , ,]
new Array(3, 11, 8); // [3, 11, 8]

// Array.of方法可以用下面的代码模拟实现。

function ArrayOf() {
  return [].slice.call(arguments);
}


二.数组填充

Array.fill()方法

fill()方法,使用自己想要的参数替换原数组内容,但是会改变原来的数组。

该方法有三个参数: fill(value, start, end) value:想要替换的内容。 start:开始位置(数组的下标),可以省略。 end:替换结束位置(数组的下标),如果省略不写就默认为数组结束。

使用小例

1.采用一个默认值填初始化数组

const a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
a1.fill(7)
console.log('%s', a1)

运行结果:

7,7,7,7,7,7,7,7,7,7,7

2.制定开始和结束位置填充。

实际填充结束位置是前一位。

const a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
a2.fill(7, 2, 5)
console.log('%s', a2)

运行结果:

1,2,7,7,7,6,7,8,9,10,11

3.结束位置省略。

从起始位置到最后。

const a3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
a3.fill(7, 2)
console.log('%s', a3)

运行结果:

1,2,7,7,7,7,7,7,7,7,7


三.数组遍历

1、Array.prototype.forEach

forEach方法最大的好处就是便于使用,而且不用定义额外的参数变量。

var a = [1,2,3];
a.forEach(function(value,key,arr){
  console.log(value)    // 结果依次为1,2,3
  console.log(key)      // 结尾依次为0,1,2
  console.log(arr)      // 三次结果都为[1,2,3],该参数貌似没什么用
})

但是从效率以及性能角度来说它是劣于原始for循环的,而且也不能强制return结束循环,原因如下: forEach循环一看就是通过回调函数来提供参数的,而回调函数在JS中是闭包的一种,闭包的作用是用来生成私有作用域的,所以,每一个回调函数都是一个独立的作用域,都拥有自己独立的存储空间,互不影响,而且内部变量还不及时释放,这也就是为什么在能不用闭包的情况下就不要用闭包的原因,而在闭包中return的话,也只是在当前回调函数中返回了,可是forEach中的其他的回调函数(闭包)仍然存在,所以,导致return是没办法结束循环的。下面写一个forEach循环实现例子供大家参考理解:

Array.prototype.forEachCopy = function(callback){
    var arr =  this;
    for(var i=0;i<arr.length;i++){
        callback(arr[i],i,this);
    }
}
var a = [1,2,3];
a.forEachCopy(function(value,key,arr){
    console.log(value)    // 结果依次为1,2,3
    console.log(key)      // 结尾依次为0,1,2
    console.log(arr)      // 三次结果都为[1,2,3]
})

2、Array.prototype.map

map和forEach不同,在forEach中return语句是没有任何效果的,而map则可以改变当前循环的值,并且最终会返回一个新的被改变过值之后的数组(map如果不用return就和forEach一样了),由于这个特性,map一般用来处理需要修改某一个数组的值。

var a = [1,2,3];
var b = a.map(function(value,key,arr){
    console.log(value)    // 结果依次为1,2,3
    console.log(key)      // 结尾依次为0,1,2
    console.log(arr)      // 三次结果都为[1,2,3]
    return value+1;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 2, 3, 4 ]

map和forEach在其他的方面都是一样的,也不能return结束循环等特性。像这样:

Array.prototype.mapCopy = function(callback){
    var arr =  this;
    var arrCopy = [];
    for(var i=0;i<arr.length;i++){
        var cbValue = callback(arr[i],i,this);
        arrCopy.push(cbValue);
    }
    return arrCopy;
}
var a = [1,2,3];
var b = a.mapCopy(function(value,key,arr){
    console.log(value)    // 结果依次为1,2,3
    console.log(key)      // 结尾依次为0,1,2
    console.log(arr)      // 三次结果都为[1,2,3]
    return value+1;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 2, 3, 4 ]

3、Array.prototype.filter

例子

var a = [1,2,3];
var b = a.filter(function(value,key,arr){
    console.log(value)    // 结果依次为1,2,3
    console.log(key)      // 结尾依次为0,1,2
    console.log(arr)      // 三次结果都为[1,2,3]
    if(value === 3){
      return false;
    }
    return true;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 1,2 ]

filter和map不同,map目的是为了改变值,而filter目的是为了去掉不要的值,在循环的时候如果返回的是false那么就表示本次循环的不添加该值,返回true则相反是表示要添加到新建的数组中,下面写一个filter循环实现例子:

Array.prototype.filterCopy = function(callback){
    var arr =  this;
    var arrCopy = [];
    for(var i=0;i<arr.length;i++){
        var cbValue = callback(arr[i],i,this);
        if(cbValue){
          arrCopy.push(arr[i]);
        }
    }
    return arrCopy;
}
var a = [1,2,3];
var b = a.filterCopy(function(value,key,arr){
    console.log(value)    // 结果依次为1,2,3
    console.log(key)      // 结尾依次为0,1,2
    console.log(arr)      // 三次结果都为[1,2,3]
    if(value === 3){
      return false;
    }
    return true;
})
console.log(a); // 结果为[ 1, 2, 3 ]
console.log(b); // 结果为[ 1,2 ]

4、Array.prototype.reduce

例子

var a = [1,2,3];
var b = a.reduce(function (count, value,key,arry) {
  console.log(count);   // 结果依次为0,1,3
  console.log(value);   // 结果依次为1,2,3
  console.log(key);     // 结果依次为0,1,2
  console.log(arry)     // 三次结果都为[1,2,3]
  return count + value;
},0);
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b)          // 结果为6

reduce的不同之处在于累加,和其他几个内置方法不同的地方,它的第二个参数不是this对象,而是初始累加值(如果不设置的话数组会乱掉),而且回调函数的的个数也不同,比其他的多了一个,而且还在在开始的多加了一个参数,第一个参数记录的是上一次循环的累加值,下面写一个reduce循环实现例子:

Array.prototype.reduceCopy = function(callback,countInit){
    var arr =  this;
    for(var i=0;i<arr.length;i++){
        var cbValue = callback(countInit,arr[i],i,this);
        countInit = cbValue;
    }
    return countInit;
}
var a = [1,2,3];
var b = a.reduceCopy(function (count, value,key,arry) {
  console.log(count);   // 结果依次为0,1,3
  console.log(value);   // 结果依次为1,2,3
  console.log(key);     // 结果依次为0,1,2
  console.log(arry)     // 三次结果都为[1,2,3]
  return count + value;
},0);
console.log(a);         // 结果为[ 1, 2, 3 ]
console.log(b)          // 结果为6

暂时先记录这么多,以后再补充。