盘一盘数组方法

# 盘一盘数组方法

# 集合类

# forEach

只是遍历一次数组,没有返回值

# map

遍历一次数组,返回新的数组

# filter

遍历一次数组,当前回调若返回 true,则 push 该元素进返回值数组;若为 false,跳过该元素

# reduce

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值reduce() 方法接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce() 的数组

# reduceRight

reduceRight()方法的功能和 reduce()功能是一样的,不同的是 reduceRight()从数组的末尾向前将数组中的数组项做累加。

# 检索类

# findIndex

返回 callback 结果为 true 的元素的下标,没找到返回-1

# find

findfindIndex的唯一区别在于,它返回的是实际值,而不是索引。可以重用已经实现的findIndex实现find

# indexOf

获取给定值的索引

# lastIndexOf

返回数组中最后一个元素的索引

# every

一假即假

every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试,它返回一个布尔值。

等价于逻辑与(&&)的数组

# some

一真即真

some 方法与 every 刚好相反,即只要其中一个为true 就会返回true

等价于逻辑或(||)数组

# includes

判断数组是否含有给定值

# 操作数组内容类

# concat

合并多个数组,返回新数组。纯函数

# join

将数组中所有元素用给定字符拼接成字符串。纯函数

# sort

按照a , b 两个元素a - b升序,b - a降序,排序原数组。副作用

如果没有指明 compareFunction ,那么元素会按照转换为的字符串的逐个字符的Unicode 位点进行排序。

sort 底层原理 (opens new window)

# reverse

数组中元素的位置反转,返回原数组。副作用

# shift

删除数组头部一个元素并返回该元素。副作用

# unshift

添加一个或多个元素到数组头部。副作用

# pop

pop()方法从数组中删除最后一个元素,并返回该元素的值。副作用

# push

push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。副作用

# slice

slice 会返回原数组中索引从 beginend 的所有元素 [beginend)。纯函数

# 左闭右开

  • 编程中常听到的概念都是左闭右开,slice 也是 含左不含右 ,[A, B)。
  • Math.random()产生范围在 [0,1)的数

# 举例

const arr = ['a', 'b', 'c', 'd', 'e', 'f'];
arr.slice(); // 无参数时,截取所有的元素。
arr.slice(2); // 从第二个值开始提取,直到末尾
arr.slice(-2); // 提取最后两个元素 负数会将其与长度相加,-2+6=4
arr.slice(2, 4); // 提取从第二个到第四个之间的元素(不包括第四个元素)
arr.slice(4, 2); // 空

扩展

以前会用 slice()将伪数组,转化为真数组。

// 方式1
let array = Array.prototype.slice.call(arr);
// 方式2
let array = [].slice.call(arr);
// ES6 版
let array = Array.from(arr);
// 可迭代对象
let array = [...arr];

# splice

splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,

并以数组形式返回被修改的内容

副作用

// 新数组 = 原数组.splice(起始索引index, 需要删除的个数);
// 新数组 = 原数组.splice(起始索引index, 需要删除的个数, 新的元素1, 新的元素2...);
var arr1 = ['a', 'b', 'c', 'd', 'e', 'f'];
arr1.splice(1); // 从第index为1的位置开始,删除元素
arr2.splice(-2); // 删除最后两个元素,和slice同样的思想。
arr3.splice(1, 3); // 从第index为1的位置开始删除元素,一共删除三个元素
// 增加系列
arr4.splice(1, 0, 'g', 'h'); // 纯增加情况
// 替换的情况就是 先删除再增加
arr4.splice(1, 3, 'js', 'vue'); // 删除+增加 == 更改

# fill

用一个占位符值填充一个空数组,可以使用fill方法。多用于初始化数组。副作用

# 拍平类

# flat

flat方法通过可指定深度值来减少嵌套的深度。纯函数

# flatMap

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。纯函数

# 生成器类

# values

values方法返回一个生成器,该生成器生成数组的值。

# keys

keys方法返回一个生成器,该生成器生成数组的索引。

# entries

entry方法返回生成键值对的生成器。

# 改变原数组

splicereversesortpushpopshiftunshiftfill


# 对比几个循环

# forEach 和 for 的区别

  1. for 循环可以使用 break 跳出循环,但 forEach 不能
  2. forEach 中使用 return 会跳过一次迭代
  3. for 可以用 continue 跳过循环中的一个迭代,forEach 用 continue 会报错
  4. for 循环可以控制循环起点(i 初始化的数字决定循环的起点),forEach 只能默认从索引 0 开始
  5. for 循环过程中支持修改索引(修改 i),但 forEach 做不到(底层控制 index 自增,我们无法左右它)

# for of 和 for in

  1. for...of是 ES6 引入的循环方法,内部调用的是Symbol.iterator方法

  2. for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串

  3. for...in循环读取键名,for...of循环读取键值。如果要通过for...of循环,获取数组的索引,可以借助数组实例的entries方法和keys方法

  4. for...of不能遍历对象,因为Object没有内建迭代器对象

  5. 使用for in会遍历数组所有的可枚举属性,包括原型,如果不想遍历原型方法和属性的话,可以在循环内部判断一下,使用hasOwnProperty()方法可以判断某属性是不是该对象的实例属性

    var arr = [1, 2, 3];
    Array.prototype.a = 123;
    
    for (let index in arr) {
      let res = arr[index];
      console.log(res);
    }
    //1 2 3 123
    
    for (let index in arr) {
      if (arr.hasOwnProperty(index)) {
        let res = arr[index];
        console.log(res);
      }
    }
    // 1 2 3
    

# map 和 forEach

  1. map 返回新数组,forEach无返回值
  2. map可以使用 break 中断循环,forEach不能使用 break 中断循环
  3. forEach会改变原始的数组的值,而map是纯函数。(当然,两者可以互相实现彼此的功能)

# 数组去重

# 1. 双循环遍历去重

双重 for(或 while)循环是比较笨拙的方法,它实现的原理很简单:先定义一个包含原始数组第一个元素的数组,然后遍历原始数组,将原始数组中的每个元素与新数组中的每个元素进行比对,如果不重复则添加到新数组中,最后返回新数组;因为它的时间复杂度是 O(n^2),如果数组长度很大,那么将会非常耗费内存

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  let res = [arr[0]];
  for (let i = 1; i < arr.length; i++) {
    let flag = true;
    for (let j = 0; j < res.length; j++) {
      if (arr[i] === res[j]) {
        flag = false;
        break;
      }
    }
    if (flag) {
      res.push(arr[i]);
    }
  }
  return res;
}

# 2. IndexOf 去重

# 思路 1

数组的 indexOf()方法可返回某个指定的元素在数组中首次出现的位置。该方法首先定义一个空数组 res,然后调用 indexOf 方法对原来的数组进行遍历判断,如果元素不在 res 中,则将其 push 进 res 中,最后将 res 返回即可获得去重的数组

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    if (res.indexOf(arr[i]) === -1) {
      res.push(arr[i]);
    }
  }
  return res;
}

# 思路 2

利用 indexOf 检测元素在数组中第一次出现的位置是否和元素现在的位置相等,如果不等则说明该元素是重复元素

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  return Array.prototype.filter.call(arr, function (item, index) {
    return arr.indexOf(item) === index;
  });
}

# 3. sort 去重

这种方法首先调用了数组的排序方法 sort(),然后根据排序后的结果进行遍历及相邻元素比对,如果相等则跳过该元素,直到遍历结束

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  arr = arr.sort();
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] !== arr[i - 1]) {
      res.push(arr[i]);
    }
  }
  return res;
}

# 4. 利用对象属性去重

创建空对象,遍历数组,将数组中的值设为对象的属性,并给该属性赋初始值 1,每出现一次,对应的属性值增加 1,这样,属性值对应的就是该元素出现的次数了

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  let res = [],
    obj = {};
  for (let i = 0; i < arr.length; i++) {
    if (!obj[arr[i]]) {
      res.push(arr[i]);
      obj[arr[i]] = 1;
    } else {
      obj[arr[i]]++;
    }
  }
  return res;
}

# 5. set 与结构赋值去重

ES6 中新增了数据类型 set,set 的一个最大的特点就是数据不重复。Set 函数可以接受一个数组(或类数组对象)作为参数来初始化,利用该特性也能做到给数组去重

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  return [...new Set(arr)];
}

# 6. Array.from 与 set 去重

Array.from 方法可以将 Set 结构转换为数组结果,而我们知道 set 结果是不重复的数据集,因此能够达到去重的目的

function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log('type error!');
    return;
  }
  return Array.from(new Set(arr));
}

# 具体去重比较

将这样一个数组按照上面的方法去重后的比较:

var array = [
  1,
  1,
  '1',
  '1',
  null,
  null,
  undefined,
  undefined,
  new String('1'),
  new String('1'),
  /a/,
  /a/,
  NaN,
  NaN,
];
方法 说明 结果
双层 for 循环 对象和 NaN 不去重 [1, "1", null, undefined, String, String, /a/, /a/, NaN, NaN]
Array.sort()加一行遍历冒泡 对象和 NaN 不去重 数字 1 也不去重 [/a/, /a/, "1", 1, String, 1, String, NaN, NaN, null, undefined]
Array.filter()加 indexOf 对象不去重 NaN 会被忽略掉 [1, "1", null, undefined, String, String, /a/, /a/]
Object 键值对去重 全部去重 [1, "1", null, undefined, String, /a/, NaN]
ES6 中的 Set 去重 对象不去重 NaN 去重 [1, "1", null, undefined, String, String, /a/, /a/, NaN]