Skip to content

arrayApi

数组常用API

属性说明
map遍历数组,不影响原数组
filter过滤,不影响原数组
concat遍历数组,不影响原数组
push/pop末尾推入和末尾弹出,影响原数组
unshift/shift头部推入和头部弹出,影响原数组
sort排序与反转,影响原数组
slice返回截断后的新数组,不影响原数组
splice返回删除元素组成的数组,value 为插入项,影响原数组
join数组转换成字符串,不影响原数组
split字符串将数组转换成数组不影响原数组
forEach无法 break,可以用 try/catch中 thrownewError来停止
some有一项返回 true,则整体为 true
every有一项返回 false,则整体为 false
indexOf/lastIndexOf查找数组项,返回对应的下标
reduce/reduceRight两两执行,prev 为上次化简函数的 return值,cur 为当前值(从第二项开始)

slice、splice

  • slice 返回截断后的新数组,不影响原数组
  • splice 返回删除元素组成的数组,value 为插入项,影响原数组

join、split

  • join 将数组转换成字符串,不影响原数组
  • split 字符串将数组转换成数组不影响原数组

数组、对象不会自动加分号,会拼接上去

js
let a = [1, 2, 3]
[2] // => [1,2,3][2]
console.log(a); // 3

let b = { x: 10 }
["x"]; // => {'x':10}['x']

console.log(b); // 10

indexOf,includes 区别?

  • indexOf 返回的是数值类型,并且 indexOf 不能查找 NaN
  • includes 返回的布尔类型,includes 可以查询 NaN
js
let arr = [1, 2, NaN];
console.log(arr.indexOf(NaN)); // -1
console.log(arr.includes(NaN)); // true

类数组的特征,需要有 length、push 属性

js
let arrayLike = {
  0: "a",
  1: "b",
  4: "4",
  length: 2,
  push: Array.prototype.push,
};
console.log(arrayLike.length); // 2
console.log(arrayLike[0]); // a
console.log(arrayLike[1]); // b
console.log(arrayLike[2]); // undefined length到2就结束
arrayLike.push(100); // 只有调用push 操作会修改长度(push源码解析)
console.log(arrayLike.length); // 3
console.log(arrayLike[2]);

// 数组push源码,存储索引的值,长度+1
function push(val) {
  this[this.length] = val;
  this.length = ++this.length;
}

// 类数组转数组
console.log(Array.from(arrayLike));

数组长度问题

js
const arr1 = [1];
const arr2 = [1, ,];
const arr3 = new Array("10"); // 创建长度为1的数组,元素的值是10
const arr4 = new Array(10); // 创建长度为10的数组,10个元素都是empty

console.log(arr1.length, arr1); // 1 [1]
console.log(arr2.length, arr2); // 2 (2) [1, 空白]
console.log(arr3.length, arr3); // 1 ['10']
console.log(arr4.length, arr4); // 10 [空属性 × 10]

数组空元素 empty,在 map、forEach...,遍历时会跳过

js
function createData() {
  return new Array(1000).map((v, i) => () => {
    return { name: `name${i + 1}` };
  });
}

const data = createData();
console.log(data); // [empty × 1000]

数组 entries 实现

js
// entries next
Array.prototype.entries = function () {
  const O = Object(this);
  let index = 0;
  const len = O.length;
  function next() {
    if (index < len) {
      return { value: [index, O[index++]], done: false };
    }
    return { value: undefined, done: true };
  }
  return {
    next,
    // 可迭代
    [Symbol.iterator]: function () {
      return {
        next,
      };
    },
  };
};
let arr = [1, 2, 3];
let n = arr.entries();
console.log(n.next());
console.log(n.next());
console.log(n.next());
console.log(n.next());

for (let [k, v] of arr.entries()) {
  console.log(`k:${k}`, `v:${v}`);
}

数组 includes 实现

js
function ToIntegerOrInfinity(argument) {
  var num = Number(argument);
  // + 0 和 -0
  if (Number.isNaN(num) || num == 0) {
    return 0;
  }
  if (num === Infinity || num == -Infinity) {
    return num;
  }
  var inter = Math.floor(Math.abs(num));
  if (num < 0) {
    inter = -inter;
  }
  return inter;
}

Array.prototype.includes = function (item, fromIndex) {
  // call, apply调用,严格模式
  if (this == null) {
    throw new TypeError("无效的this");
  }
  var O = Object(this);

  var len = O.length >> 0;
  if (len <= 0) {
    return false;
  }

  var n = ToIntegerOrInfinity(fromIndex);
  if (fromIndex === undefined) {
    n = 0;
  }
  if (n === +Infinity) {
    return false;
  }
  if (n === -Infinity) {
    n = 0;
  }

  var k = n >= 0 ? n : len + n;
  if (k < 0) {
    k = 0;
  }

  const isNAN = Number.isNaN(item);
  for (let i = k; i < len; i++) {
    if (O[i] === item) {
      return true;
    } else if (isNAN && Number.isNaN(O[i])) {
      return true;
    }
  }
  return false;
};

const arr = ["a", "b", "c"];
console.log("arr include -100->0:", arr.includes("c", -100));
console.log("arr include -100->0:", arr.includes("a", -1));
console.log("arr include 1:", arr.includes("a", -Infinity));
console.log("arr include 1:", arr.includes("a", Infinity));

数组扁平化

js
const nums = [1, 2, [3, 4, [100, 200], 5], 6]
// 数组元素是 {x: 100} 等引用类型,就不可以了
nums.toString() // '1,2,3,4,100,200,5,6'

// 正无穷
nums.flat(Infinity) // [1, 2, 3, 4, 100, 200, 5, 6]

// 递归
function flatten(arr=[],newArr=[]){
  arr.forEach((_)=>{
    if(Array.isArray(_)){
      flatten(_,newArr)
    }else{
      newArr.push(_)
    }
  })
  return newArr;
}
console.log(flatten(nums))