JS数组总结(一)

151 阅读7分钟

一:数组基础

1. 数组概述

在ES6中,可以使用扩展运算符(...)来获取数组元素:

let a = [1, 2, 3];
let b = [0, ...a, 4];  // [0, 1, 2, 3, 4]

2. 数组创建

(1)字面量(常用)

let colors = ["red", [1, 2, 3], true];  

(2)构造函数

let array = new Array(); 

(3)ES6 构造器

ES6 专门扩展了数组构造器 Array ,新增了 2 个方法:Array.of和Array.from。

从语法上看,Array.from 有 3 个参数:

  • 类似数组的对象,必选;
  • 加工函数,新生成的数组会经过该函数的加工再返回;
  • this 作用域,表示加工函数执行时 this 的值。
var obj = {0: 'a', 1: 'b', 2:'c', length: 3};

Array.from(obj, function(value, index){
  console.log(value, index, this, arguments.length);
  return value.repeat(3);   //必须指定返回值,否则返回 undefined
}, obj);

除了上述 obj 对象以外,拥有迭代器的对象还包括 String、Set、Map 等,Array.from 都可以进行处理:

// String
Array.from('abc');                             // ["a", "b", "c"]
// Set
Array.from(new Set(['abc', 'def']));           // ["abc", "def"]
// Map
Array.from(new Map([[1, 'ab'], [2, 'de']]));   // [[1, 'ab'], [2, 'de']]

数组判断

在 ES6 之前,至少有如下 5 种方式去判断一个对象是否为数组。

1、通过Object.prototype.toString.call() 做判断:

Object.prototype.toString.call(obj).slice(8,-1) === 'Array';

2、通过constructor做判断:

obj.constructor === Array;

3、 通过instanceof做判断:

obj instanceof Array

4、 通过Array.prototype.isPrototypeOf做判断:

Array.prototype.isPrototypeOf(obj)

5、通过基于getPrototypeOf做判断:

Object.getPrototypeOf(obj) === Array.prototype;

ES6 新增了 Array.isArray 方法,可以直接判断数据类型是否为数组:

Array.isArrray(obj);

如果 isArray 不存在,那么 Array.isArray 的 polyfill 通常可以这样写:

if (!Array.isArray){
  Array.isArray = function(arg){
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

二、数组方法

数字就像是一个森林,里面有很多函“树”,有些方法纯净如水,并不会改变原数组,有些则会改变原数组。

  • 改变原数组的方法:fill()、pop()、push()、shift()、splice()、unshift()、reverse()、sort();
  • 不改变原数组的方法:concat()、every()、filter()、find()、findIndex()、forEach()、indexOf()、join()、lastIndexOf()、map()、reduce()、reduceRight()、slice()、some。

1. 复制和填充方法

ES提供了两个方法:批量复制方法copeWithin(),以及填充数组方法fill()。这两个方法的签名类似,都需要指定已有数组实例上的一个范围,包含开始索引,不包含结束索引。下面就分别来看一下这两个方法。

(1)fill()

使用fill()方法可以向一个已有数组中插入全部或部分相同的值,开始索引用于指定开始填充的位置,它是可选的。如果不提供结束索引,则一直填充到数组末尾。如果是负值,则将从负值加上数组的长度而得到的值开始。

(2)copyWithin()

copyWithin()方法会按照指定范围来浅复制数组中的部分内容,然后将它插入到指定索引开始的位置,开始与结束索引的计算方法和fill方法一样。

2. 转化方法

数组的转化方法主要有四个:toLocaleString()、toString()、valueOf()、join()。下面就分别来看一下这4个方法。

(1)toString()

toString()方法返回的是由数组中每个值的等效字符串拼接而成的一个逗号分隔的字符串,也就是说,对数组的每个值都会调用toString()方法,以得到最终的字符串:

let colors = ["red", "blue", "green"];  
console.log(colors.toString())  // red,blue,green

(2)valueOf()

valueOf()方法返回的是数组本身,如下面代码:

let colors = ["red", "blue", "green"];  
console.log(colors.valueOf())  // ["red", "blue", "green"]

(3)toLocaleString()

toLocaleString()方法可能会返回和toString()方法相同的结果,但也不一定。在调用toLocaleString()方法时会得到一个逗号分隔的数组值的字符串,它与toString()方法的区别是,为了得到最终的字符串,会调用每个值的toLocaleString()方法,而不是toString()方法,看下面的例子:

let array= [{name:'zz'}, 123, "abc", new Date()];
let str = array.toLocaleString();
console.log(str); // [object Object],123,abc,2016/1/5 下午1:06:23

需要注意,如果数组中的某一项是null或者undefined,则在调用上述三个方法后,返回的结果中会以空字符串来表示。

4)join()

join() 方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的。其使用语法如下:

该方法返回一个字符串。该字符串是通过把 arrayObject 的每个元素转换为字符串,然后把这些字符串连接起来,在两个元素之间插入 separator 字符串而生成的。

let array = ["one", "two", "three","four", "five"];
console.log(array.join());      // one,two,three,four,five
console.log(array.join("-"));   // one-two-three-four-five

3. 栈方法

ECMAScript给数组添加了几个方法来使它像栈一样。众所周知,栈是一种后进先出的结构,也就是最近添加的项先被删除。数据项的插入(称为推入,push),和删除(称为弹出,pop)只在栈顶发生。数组提高了push()和pop()来实现类似栈的行为。下面就分别来看看这两个方法。

(1)push()

push()方法可以接收任意数量的参数,并将它们添加了数组末尾,并返回数组新的长度。该方法会改变原数组。

(2)pop()

pop() 方法用于删除并返回数组的最后一个元素。它没有参数。该方法会改变原数组。

4. 队列方法

队列是一种先进先出的数据结构,队列在队尾添加元素,在对头删除元素。上面我们已经说了在结果添加数据的方法push(),下面就再来看看从数组开头删除和添加元素的方法:shift()和unshift()。实际上unshift()并不属于操作队列的方法

(1)shift()

shift()方法会删除数组的第一项,并返回它,然后数组长度减一,该方法会改变原数组。

注意:如果数组是空的,那么 shift() 方法将不进行任何操作,返回 undefined 值。

(2)unshift()

unshift()方法可向数组的开头添加一个或更多元素,并返回新的长度。该方法会改变原数组。

5. 排序方法

数组有两个方法可以对数组进行重新排序:sort()和reverse()。下面就分别来看看这两个方法。

(1)sort()

sort()方法是我们常用给的数组排序方法,该方法会在原数组上进行排序,会改变原数组,其使用语法如下:

let array = [0, 1, 5, 10, 15];

let array2 = array.sort((a, b) => a - b);  // 正序排序
console.log(array2)  // [0, 1, 5, 10, 15]

let array3 = array.sort((a, b) => b - a);  // 倒序排序
console.log(array3)  // [15, 10, 5, 1, 0]

(2)reverse()

reverse() 方法用于颠倒数组中元素的顺序。该方法会改变原来的数组,而不会创建新的数组。其使用语法如下:

let array = [1,2,3,4,5];
let array2 = array.reverse();
console.log(array);   // [5,4,3,2,1]
console.log(array2 === array);   // true

6. 操作方法

对于数组,还有很多操作方法,下面我们就来看看常用的concat()、slice()、splice()方法。

(1)concat()

concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

(2)slice()

slice() 方法可从已有的数组中返回选定的元素。返回一个新的数组,包含从 start 到 end (不包括该元素)的数组元素。方法并不会修改数组,而是返回一个子数组。

let array = ["one", "two", "three", "four", "five"];
console.log(array.slice(0));    // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3)); // ["three"]

(3)splice()

splice()方法,使用它的形式有很多种,它会向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。其使用语法如下: 其参数如下:

  • index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
  • howmany:必需。要删除的项目数量。如果设置为 0,则不会删除项目。
  • item1, ..., itemX:可选。向数组添加的新项目。

从上面参数可知,splice主要有三种使用形式:

  • 删除: 需要给splice()传递两个参数,即要删除的第一个元素的位置和要删除的元素的数量;

  • 插入: 需要给splice()传递至少三个参数,即开始位置、0(要删除的元素数量)、要插入的元素。

  • 替换: splice()方法可以在删除元素的同事在指定位置插入新的元素。同样需要传入至少三个参数,即开始位置、要删除的元素数量、要插入的元素。要插入的元素数量是任意的,不一定和删除的元素数量相等。

使用示例如下:

let array = ["one", "two", "three","four", "five"];
console.log(array.splice(1, 2));           // 删除:["two", "three"]

let array = ["one", "two", "three","four", "five"];
console.log(array.splice(2, 0, 996));      // 插入:[]

let array = ["one", "two", "three","four", "five"];
console.log(array.splice(2, 1, 996));      // 替换:["three"]