JS数组

最近在学习《数据结构与算法》,数据结构中数组的重要性不言而喻。 由于 js 随意的动态性,总结一下数组的用法。

Array

array 定义

  1. 通过 new Array 创建数组时, 如果是一个参数且必须是个正整数,就是在定义长度。若是多个参数,则是赋值。
    1
    var arr = new Array(5); //定义数组长度

ps: 在我看来,这是最不负责任的数组。

  1. Array如果通过索引赋值时,索引超过了范围,同样会引起ƒ大小的变化。
    大多数其他编程语言不允许直接改变数组的大小(如:java),越界访问索引会报错。然而,JavaScript的Array却不会有任何错误。在编写代码时,不建议直接修改Array的大小,访问索引时要确保索引不会越界。
    1
    2
    3
    var arr = [1, 2, 3];
    arr[5] = 'x';
    arr; // arr变为[1, 2, 3, undefined, undefined, 'x']

同理,修改 arr.length 的值,一样改变数组长度。

改变原数组的方法 [push, pop, shift, unshift, sort, reverse, splice]

  1. push 与 pop
    与 数据 stack 的 push、pop 方法概念相同,先进后出。
    由于 length 随意更改,可得 push 的实现原理:

    1
    2
    3
    4
    5
    Array.prototype.myPush = function () {
    for (let i = 0; i < arguments.length; i++) {
    this[this.length] = arguments[i];
    }
    }
  2. unshift 和 shift
    如果要往Array的头部添加若干元素,使用unshift()方法,shift()方法则把Array的第一个元素删掉:

    1
    2
    3
    4
    5
    6
    7
    Array.prototype.myUnShift = function () {
    var newArr = []
    for (let i = 0; i < arguments.length; i++) {
    newArr[i] = arguments[i];
    }
    return newArr.concat(this);
    }

要注意的是 arguments 是个类数组对象,无法直接使用 concat 方法。

  1. splice 切片

splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:
splice(开始切,截取长度,切口处加入新元素)

1
2
3
4
5
6
7
8
9
10
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只删除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']

  1. sort
    sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序:
    但是 js 中 sort 与其他语言差距较大(如:java),排序是ascII 码 排序。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var arr = ['B', 'C', 'A'];
    arr.sort();
    arr; // ['A', 'B', 'C']
    arr1 = [1,20,10,3];
    arr1.sort()
    arr1;// [1, 10, 20, 3]

    // 比较 参数,return 正数 交换位置(即:a>b),return 负数 位置不变。
    arr1.sort((a,b)=>{
    return a-b;
    })
    //[1, 3, 10, 20]

所以,以后用 sort 一定传函数,以防不测。。。
sort 传入回调函数,可以实现乱序。

1
2
3
arr1.sort(() => {
return Math.random() - 0.5;
})

不改变原数组的方法 [ concat, join, split, toString, slice]

  1. concat
    concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array
1
2
3
4
var arr = ['A', 'B', 'C'];
var added = arr.concat([1, 2, 3]);
added; // ['A', 'B', 'C', 1, 2, 3]
arr; // ['A', 'B', 'C'] //原数组 不变

注意concat()方法并没有修改当前Array,而是返回了一个新的Array

实际上,concat()方法可以接收任意个元素和Array,并且自动把Array拆开,然后全部添加到新的Array里:

1
2
var arr = ['A', 'B', 'C'];
arr.concat(1, 2, [3, 4]); // ['A', 'B', 'C', 1, 2, 3, 4]

由于数组是典型的引用类型,数组赋值等操作时需要 concat。

1
arr.push([].concat(temp))

  1. slice 截取
    slice()就是对应String的substring()版本,它截取Array的部分元素,然后返回一个新的Array
    前开后闭
    1
    2
    3
    var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
    arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C']
    arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']

如果不给slice()传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容易地复制一个Array

1
2
3
4
var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var aCopy = arr.slice();
aCopy; // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
aCopy === arr; // false //深拷贝

第三个参数是 删除位置 将替换的内容

1
arr.splice(0, 2, temp); //将 0 1替换 temp

  1. join
    join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串:
1
2
var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // 'A-B-C-1-2-3'

如果Array的元素不是字符串,将自动转换为字符串后再连接。
不传参数将自动以 ‘,’ 分隔。

注意 字符串中 split() 与 join 是可逆操作。

遍历方法

[].every(fun)
:返回一个boolean,判断每个元素是否符合func条件(所有都判断)(并没有改变原数组)

[].some()
:返回一个boolean,判断是否有元素是否符合func条件(有一个就行)(并没有改变原数组)

[].filter()
:返回一个符合func条件的元素数组(并没有改变原数组)

[].forEach(fun) 不生成新数组的迭代器方法,没有返回值, 改变原数组操作

[].map(fun)
有返回值,可以return出来,返回一个新的Array.
[].reduce(function(prev,cur,index,arr),init)