js基础-2. 数组

200 阅读7分钟

2. 数组

2.1 数组创建

  1. 通过构造函数: new Array()

  2. 数组字面量。[]

  3. Array.of() 。es6

  4. Array.from(iterator, mapFn, thisArg) 从一个类似数组或可迭代对象中创建一个新的数组实例。es6


//1. new 通过构造函数

{

  let arr1 = new Array(3); //length为3的空数组[]

  let arr2 = new Array(1,2); //[1,2]

  let arr3 = new Array('grace'); //['grace]

}

//通过构造函数,创建数组,可省略关键字new

{

  let arr = Array(3,4);//[3,4]

  arr instanceof Array; //true

}

//2. [] 通过数组字面量创建

{

  let arr1 = [1, 2, 3];

  let arr2 = [,,]; //【不推荐】ie8- 3项,其他浏览器 2项

  let arr3 = [1,2,]; //【不推荐】 ie8- 3项[1, 2, undefined], 其他浏览器[1,2]

}

//3 Array.of()

{

  Array.of(2); //[2]

  Array.of(2,3); //[2,3]

}

//4 Array.from()

{

  Array.from('abc'); //['a', 'b', 'c']

  Array.from(312); //[] 数字不可迭代



  //用于数组去重,映射函数用法同map

  let set = new Set([2,2,3,3])

  Array.from(set, (item)=>{

    return item * 2

  }); //[4, 6]

}

2.2 数组读取

  1. 数组是经过优化的对象,访问速度比一般对象快;

  2. 数组索引范围:0~2^32 -2。

  3. 数组索引,是特殊的对象属性。数字索引,会转化为字符串,进行访问。可以为数组自定义属性名。但只有在索引范围的属性名,才是数组索引,才会影响数组长度。

  4. 可通过控制数组长度,增删数组


let arr = [1,2]

//字符串索引 == 数字索引

arr[1]; //2

arr['1']; //2

//数组为特殊的对象,可自定义属性

//在索引范围的属性值,为索引,改变数组长度

arr[3] = 3; // arr: [1,2,,3] | arr.length: 4

//不再索引范围的,不改变数组长度

arr['key'] = 'value'; //arr=[1,2,,3,{key: 'value'}] | arr.length: 4

2.3 数组方法

2.3.1 修改原数组
  1. 栈方法( last in first out) :push, pop

  2. 队列方法(first in first out):unshift, shift

  3. 操作方法-数组删除/插入/替换:splice

  4. 重排序方法: reverse, sort

  5. 填充数组:fill, copyWithin。es6


//push,unshift

{

  let arr = [3,4,2];

  arr.push(0); //返回新数组长度4, arr = [3,4,2,0]

}

//pop, shift

{

  let arr = [3,4,2];

  arr.pop(); //返回弹出项, arr = [3,4,2]

}

//splice

//参数:(startIndex, delNum, insertItems)

//startIndex为负时,用this.length相加

//返回包含删除项的数组

//在原数组上进行修改

{

  let arr = [1,2,3];

  //插入

  arr.splice(0,0,3,3);// arr: [3,3,1,2,3],返回[],因删除0项

  //删除

  arr.splice(0, 3); //arr: [2,3], 返回:[3,3,1]

  //替换:先删除,再插入

  arr.splice(0,1,5); //arr: [5,3], 返回: [2]



  //warning

  arr.splice(1); //[2,3]指定startIndex,但未指定删除数量时,删除到末尾

}

//reverse, sort

//修改并返回原数组

{

  let arr = [3,4,2];

  let arr2 = arr.reverse(); //arr = [3,4,2], 返回值同arr

  let arr3 = arr.sort(); //arr=[2,3,4],sort默认按照升序排列

  console.log(arr === arr2, arr === arr3); //true, true





  /*arr.sort(compareFn),可以接受一个比较函数,比较Fn两个参数

  如果第1个参数应位于第2个参数前,返回负数

  如果第1个参数应位于第2个参数后,返回正数

  如果两个参数相等,返回0

  ==》返回负数和0,不动;返回正数,前后两项交换位置。

  */

  //升序

  function compare(val1, val2){

    if(val1 < val2){

      return -1;

    }else if(val1 > val2){

      return 1;

    }else{

      return 0;

    }

  }

  //简化

  function compare(val1, val2){

    return val1 - val2;

  }

  eg:

  let obj = [{No: 3, name: 'melon'}, {No: 2, name: 'strawberry'}]

  obj.sort((item1, item2)=>{

    return item1.No - item2.No;

  });

  console.log(obj); //[{No: 2, name: 'strawberry'}, {No: 3, name: 'melon'}]

}

//fill

//参数:(val, startIndex, endIndex)

//1. start 默认为0;end 默认为 this.length。 fill替换的对象为this。

//2. start、end 为负数时。用this.length 相加。start < end时,不操作。

// 修改并返回原数组

{

  let arr = [1,2,3];

  arr.fill(5); //[5,5,5]

  arr.fill(6,1); //[5,6,6]

  arr.fill(7,1,2); //[5,7,6]

  let arr2 = arr.fill(8, -2, -1); //[5,8,6]



  console.log(arr === arr2); //true

}

//copyWithin

//参数:(pasteStart, copyStart, copyEnd)

//参数规律同 fill

//修改并返回数组

{

  let arr = [1,2,3,4];

  let arr2 = arr.copyWithin(0,2); // [3,4,3,4]

  arr.copyWithin(-2,1,3); //[3,4,4,3] pasteStart:-2 + arr.length

  arr.copyWithin(1); //[3,3,4,4] copyStartmore从0开始

  console.log(arr === arr2); //true

}

//fill vs copyWithin

//fill: 填充数组值来源于外部

//copyWithin: 填充数组与元素来源于本数组

2.3.2 不修改原数组的 :
  1. 数组转换方法:
  • 转化为字符串:toString(), toLocaleString(), join,

  • 返回数组:valueOf()


let arr = [3,4,undefined,null];

//toString, toLocaleString(), join

//undefined, null 会被转化为空字符串

{

  arr.toString(); //返回'3,4,,'

  arr.join('-'); //返回'3-4--'

  arr.join(); //返回'3,4,,'

}

//valueOf 返回数组

//valueOf结果指向arr引用地址

let arr2 = arr.valueOf(); // 返回[3,4,undefined,null]

{

  let arr = [];

  let arr1 = arr.valueOf();

  arr.push(1);

  console.log(arr); //[1]

  console.log(arr1); //[1]

}

  1. 操作方法:concat、slice

//concat

{

  let arr = [1]

  let arr2 = arr.concat(2); //[1,2]

  let arr3 = arr.concat([3,3]); //[1,3,3]

}



//slice

{

  let arr = [3,4,undefined,null];

  let arr5 = arr.slice(); // [3,4,undefined,null]

  let arr6 = arr.slice(1); //[4,undefined,null]

  let arr7 = arr.slice(1,3); //[4,undefined],不包括结束位置index

  let arr8 = arr.slice(1, -1); //等价于arr.slice(1, arr.length + (-1))

}

//slice截取数组,原数组中的引用数据类型,只拷贝了引用地址

{

  let obj = {a: 1};

  let arr = [];

  let arr1 = arr.slice();

  arr.push(obj); //arr: [{a:1}]

  let arr2 = arr.slice(); //[{a:1}]



  obj.a = 2;

  console.log(arr); //[{a:2}]

  console.log(arr2); //[{a:2}]

  console.log(arr1); //[]

}

  1. 位置方法:
  • indexOf() 、lastIndexOf()

    • 返回数组中给定元素的第一个索引。

    • 找不到返回-1。

  • find()、findIndex() 两个参数:回掉函数、this指向。 指定条件 检索数组。 es6

    • find返回第一个符合条件的元素。找不到返回undefined。

    • findIndex 返回第一个符合条件的值的索引。找不到返回-1


let arr = [1,2,3];

//indexOf() ,lastIndexOf()

{

  arr.indexOf(2); //'1'

  arr.lastIndexOf(2); //'3'

  arr.indexOf(5); //-1

}

//find, findIndex

{

  arr.find(item => item > 2); //3

  arr.find(item => item > 5); //undefined



  arr.findIndex(item => item > 2); //2

  arr.findIndex(item => item > 5); -1

}

  1. 迭代方法(ES5):均不修改原数组。每一项上调用的函数有3个参数—迭代项、该项的位置、数组本身。

    • every、some: 返回布尔型

    • filter、map:返回数组。

    • forEach: 无返回值。作用同for。按顺序遍历。


let arr = [1,2,3]

//every——检测是否所有项都满足条件

let everyRes = arr.every((item, index, arr)=>{

  console.log(this)

  return item > 2;

});

everyRes; //false



//some——检测是否存在满足条件的项

let someRes = arr.some((item,index, arr)=>{

  return item > 2;

});

someRes; //true



// filter——筛选出符合条件的项

let filterRes = arr.filter((item, index, arr)=>{

  return item >1;

});

filterRes; //[2,3]



//map——将return结果组成新数组

let mapRes = arr.map((item, index, arr)=>{

  return item * 2;

});

mapRes; //[2,4,6]



//forEach,用途相当于for

arr.forEach((item, index, arr)=>{

  console.log(item)

})

  1. 归并方法:reduce、reduceRight

    • 参数:

      • 接受2个参数。每一项上调用的函数、作为归并初始值。

      • 函数有4个参数,前一个值(prev)、当前值(cur)、当前项的索引(index)、该数组。

        • 有初始值时,第一次遍历,prev为归并初始值,cur为第一项,index为0;迭代arr.length次。

        • 无初始值时,第一次遍历,prev为第0项,cur为第2项,index为1。迭代arr.length - 1次。

    • reduce:从第一项开始

    • reduceRight:从最后一项开始


let arr = [1,2,3]

//迭代3次,从第1项开始

let reduceRes1 = arr.reduce((prev, cur, index, arr)=>{

  console.log(index);

  return prev + cur;

}, 0);

//index 0

//index 1

//index 2

//reduceRes1 6



//迭代2次,从第2项开始

let reduceRes2 = arr.reduce((prev, cur, index, arr)=>{

  console.log(index);

  return prev + cur;

});

//index 1

//index 2

//reduceRes1 6

Q:检测数组中是否存在某元素的方法:

A:indexOflastIndexOfsomefindfindIndex

2.4 类数组对象

2.4.1 类数组特点
  • 有length属性。

  • 有可转化为正整数的索引,且索引 < 2^32 - 1。

  • 只能调用数组的某些方法:

    • 3种经典类数组,可用forEach遍历法

    • 自定义类数组,不能用forEach遍历。

    • 上述两种,均可用for循环遍历。

    • slice、splice、indexOf……不适用容。可用Array.from()转化为真数组,再调用数组API。


//类数组1, domNodes

{

  let nodes = document.querySelectorAll('div');

  Array.isArray(nodes); //false

}

//类数组2,Arguments

{

  function fn(arguments){

    Array.isArray(arguments); //false

  }

  fn();

}

//类数组3,jqNOdes

{

  Array.isArray($('div')); //false

}

//创建一个类数组,不可使用

{

  let obj = {'1': 'a', '2': 'b', 'k1': 'c'};

  obj.length = 2;

  for(let i = 0; i < obj.length; i++){

    console.log(obj[i]);

  }

  obj.forEach(()=>{}); //报错

  obj.map(()=>{})



  let arr = Array.from(obj);

  console.log(arr); //[undefined, "a"] 不存在项,用undefined补上

}

2.4.2 类数组转换
  1. 遍历类数组,逐项push进一个数组中。代码较多,不简洁。且必须要有length属性。

  2. Array.prototype.slice.call()。 实用。不够直观。

  3. Array.from()。直观,能转化所有可迭代对象


let obj = {length: 3};

//遍历类数组

{

  function makeArray(arrayLike){

    let result = [];

    for(let i = 0; i < arrayLike.length; i++){

      result.push(arrayLike[i])

    }

    return result;

  }



  makeArray(obj); // [undefined, undefined, undefined]

}



//Array.prototype.slice.call()

{

  function makeArray(arrayLike){

    return Array.prototype.slice.call(arrayLike);

  }

  makeArray(obj); //[empty × 3]

}



//Array.from()

{

  function makeArray(arrayLike){

    return Array.from(arrayLike);

  }

  makeArray(obj); //undefined, undefined, undefined]

}

2.5 定型数组

(看了一边,用的时候,再过一遍)

  1. 专门用于处理数值类型。为JS提供快速的按位运算。

  2. 不可修改长度。

  3. 适用数组方法。除了修改原数组的方法和concat。因concat会混乱数据类型,不符合定型数组初衷。

  4. 类型包括:

  5. Int8Array、Uint8Array、Uint8ClapedArray

  6. Int16Array、Uint16Array

  7. Int32Array、Uint32Array

  8. Float32Array、Float32Array

  9. 创建定型数组3中方法:

  10. 数组缓冲区+ 视图缓冲区+set进数据

  11. new Int8Array()

  12. ……用到时,再了解。

tips:

  1. js数字用 64bit == 8 byte 存储一个浮点数;