Fork me on GitHub

Array笔记

前言

数组是我们平时编码中必不可少的一个重要,无论是数据的处理还是数据的传递,它都起到了至关重要的作用。无论是老版的JavaScript还是ES6都提供了大量的方法让我们来对数组进行处理。本文主要介绍Array对象的本质和它的相关属性,方法。

Array原型图

原型链示意图



分两个方向来分析

原生对象Array

作为JavaScript的原生对象Array

属性和方法

  • 按f12打开控制台输入Array.你会发现侧边出现了很长的一串的属性和方法的补全提示,这些属性和方法到底哪些是可用的又有哪些是Array对象本身的呢?我们可以试验一下。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    console.log(Array.length);
    console.log(Array.name);
    console.log(Array.from);
    console.log(Array.isArray);
    console.log(Array.of);
    console.log(Array.apply);
    console.log(Array.bind);
    console.log(Array.constructor);
    console.log(Array.toString);
    console.log(Array.hasOwnProperty);
    console.log(Array.isPrototypeOf);
    console.log(Array.toLocaleString);
    console.log(Array.valueOf);

    console.log(Array.arguments);
    console.log(Array.call);
    console.log(Array.caller);
  • 打印结果

  • 除了最后的3个属性报错其他的属性或方法全部被打印出来,但是这些不一定就是Array的本身的属性和方法。首先Array可以作为函数实例对象实际上可以看做是通过new Function()创建的,所以它继承了Function原型对象上的属性和方法,而Function.prototype作为对象是可以继承Object原型对象上的属性和方法。所以Array也继承了Object原型对象上的属性和方法。

  • 我们可以通过Object的hasOwnProperty方法来判断哪些才是真正的属于Array对象的属性和方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    console.log(Array.hasOwnProperty("length"));
    console.log(Array.hasOwnProperty("name"));
    console.log(Array.hasOwnProperty("from"));
    console.log(Array.hasOwnProperty("isArray"));
    console.log(Array.hasOwnProperty("of"));
    console.log(Array.hasOwnProperty("apply"));
    console.log(Array.hasOwnProperty("bind"));
    console.log(Array.hasOwnProperty("constructor"));
    console.log(Array.hasOwnProperty("toString"));
    console.log(Array.hasOwnProperty("hasOwnProperty"));
    console.log(Array.hasOwnProperty("isPrototypeOf"));
    console.log(Array.hasOwnProperty("toLocaleString"));
    console.log(Array.hasOwnProperty("valueOf"));
    //打印结果
    true
    true
    true
    true
    true
    false
    false
    false
    false
    false
    false
    false
    false

    通过上面的分析我们知道了Array作为对象其实只拥有lengthname两个属性和formisArrayof这3个方法。

    注意:这里还有几个继承的方法和属性我没有一一列举出来更多属性可见详情[Array][4]

属性和方法使用

length属性

返回Array对象的长度。这里的length属性只是Array本身的length属性,其值为1。

name属性

返回Array对象名称。与length属性一样,其值为Array

form方法

转换其它类型的数据并返回一个新的数组。

  • 参数1:要转换的数据
  • 用法:

  1. 将类数组对象转换为真正数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    let fakeArray = {
    0: "csz",
    1: "women",
    2: "21",
    3: ["say","sleep","drink"],
    'length': 4
    }
    console.log(Array.from(fakeArray))
    // ["csz", "women", "21", ["say","sleep","drink"]]

    注意:要将一个类数组对象转换为一个真正的数组,必须具备以下条件:

    • 该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
    • 该类数组对象的属性名必须为数值型或字符串型的数字。如果不是转成的数组的值全是undefined
  2. 用法:将Set结构的数据转换为真正的数组: 

    1
    2
    3
    4
    let arr = [1,2,3,4,5,5,6]
    let set = new Set(arr);
    console.log(Array.from(set));
    // [1,2,3,4,5,6]
  3. 用法:将字符串转换为数组:返回分割字符串形成的数组。

    1
    2
    3
    let str = 'foo';
    console.log(Array.from(str));
    // ["f","o","o"]
  4. 用法:Array.from参数是一个真正的数组:返回原数组。

    1
    2
    console.log(Array.from([1,2,3,4,5]))
    // [1,2,3,4,5]
  • 参数2:回调函数
  • 用法:
1
2
3
let arr = [1, 2, 3, 4, 5];
console.log(Array.from(arr, item => item + 1));
// [2,3,4,5,6];

isArray方法

用于判断一个对象是否为数组。

  • 参数1:要判断的数据
  • 用法:

1
2
3
4
5
6
7
8
9
10
let arr = [1,2,3];
let str = "123";
let num = 123;
Array.isArray(arr);
Array.isArray(str);
Array.isArray(num);
// 打印结果
true
false
false

of方法

用于创建一个新的数组。

  • 参数1:创建的数据的元素
  • 用法:

1
2
3
4
5
6
7
let arr = Array.of(1);
let arr2 = Array.of(2);
let arr3 = Array.of(1,2,3,4);
//
[1]
[5]
[1,2,3,4]

注意:formof都是ES6新增的方法。

函数Array

作为构造函数调用或者普通函数调用。

规范

当数组作为函数调用而不是构造函数调用时,它会创建并初始化一个新的数组对象。因此当Array(...)new Array(...)接收同样的参数时,它们是相同的。

1
2
3
4
let arr = Array(1,3);
// [1,3];
let arrs = new Array(1,3);
// [1,3];

传参

  1. 传入多个数值或者多个其它类型的数据的时候,直接以【,】分割这些数据形成一个新的数组。

    1
    2
    3
    4
    let arrStr = new Array("1", "2");
    //["1","2"]
    let arrObj = new Array({name: "csz"}, {"age": 12});
    //[{name: "csz"}, {age: 12}]
  2. 传入一个0232-1之间的整数,会把它识别为创建的数组的长度,会创建一个这个以这个整数位长度,每一项都是undefined的数组。

    1
    2
    3
    let arr = new Array(3);
    console.log(arr[0], arr[1], arr.length);
    // undefined, undefined, 3
  3. ES6新增的of方法没有第二种传参方式。

实例方法(ES5)

不管是通过字面量还是new Array亦或者是Array.of()创建的实例对象,它们的__proto__属性都是指向了Array的原型对象,就继承了原型对象上的属性和方法。

Array.prototype.

forEach()方法

  1. 两个参数:
    • callback接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. arrayforEach方法被调用的数组。
    • thisArg
      1. 执行callback函数时使用的this值。
      2. 如果thisArg参数有值,则每次callback函数被调用的时候,this都会指向thisArg参数上的这个对象。如果省略了thisArg参数,或者赋值为nullundefined,则this指向全局对象。
  2. 用法:数组调用该方法,每一个元素执行callback一次。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let arr = [1, 2, 3];
    arr.forEach(function (v, i, arr) {
    console.log(v);
    arr.push(1);
    });
    console.log(arr);
    // 打印结果
    1
    2
    3
    [1,2,3,1,1,1]

shift()

  1. 参数:无。
  2. 用法:方法从数组中删除第一个元素,并返回该元素的值。此方法更改原有数组。
    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.shift()); // 1
    console.log(arr); // [2,3]

pop()

  1. 参数:无。
  2. 用法:方法从数组中删除最后一个元素,并返回该元素的值。此方法更改原有数组。
    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.pop()); // 3
    console.log(arr); // [1,2]

unshift()

  1. 一个参数
    • elementN要添加到数组开头的元素。
  2. 用法:方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。此方法更改原有数组。
    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.unshift(4, 5)); // 5
    console.log(arr); // [4,5,1,2,3]

push()

  1. 一个参数
    • elementN要添加到数组开头的元素。
  2. 用法:方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。此方法更改原有数组。
    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.push(4, 5)); // 5
    console.log(arr); // [1,2,3,4,5]

splice()

  1. 三个参数
    • start
      指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
    • deleteCount
      1. 整数,表示要移除的数组元素的个数。
      2. 如果deleteCount0或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
      3. 如果deleteCount大于start之后的元素的总数,则从start后面的元素都将被删除(含第start位)。
      4. 如果deleteCount被省略,则其相当于(arr.length - start)。
    • item1, item2, ...
      要添加进数组的元素,从start位置开始。如果不指定,则splice()将只删除数组元素。
  2. 用法:方法通过删除现有元素和/或添加新元素来修改数组,并以数组返回原数组中被修改的元素。此方法更改原有数组。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    let arr = [1, 2, 3, 4, 5];
    // start超过数组长度,且没有添加新的元素
    console.log(arr.splice(5)); //[]
    console.log(arr); //[1,2,3,4,5]

    // start不超过数组长度,且没有添加新的元素
    let arr1 = [1, 2, 3, 4, 5];
    console.log(arr1.splice(0, 2)); //[1,2]
    console.log(arr1); //[3,4,5]

    // start不超过数组长度,删除个数为0或者负数,添加新的元素
    let arr2 = [1, 2, 3, 4, 5];
    console.log(arr2.splice(0, 0, 1)); // []
    console.log(arr2); // [1,1,2,3,4,5]

    // start为负数且负数绝对值不超过数据长度,添加新的元素
    let arr3 = [1, 2, 3, 4, 5];
    console.log(arr3.splice(-3, 1, "a")); //[3]
    console.log(arr3); //[1,2,"a",4,5]

    // start为负数且负数绝对值超过数据长度,添加新的元素
    let arr4 = [1, 2, 3, 4, 5];
    console.log(arr4.splice(-6, 1, "a")); //[3]
    console.log(arr4); //["a",2,3,4,5]

slice()

  1. 两个参数:
    • start
      1. 指定截取的开始位置(从0计数)。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取。
      2. 省略就从0开始截取。
      3. 没有end就从开始位置截取,剩下的所有数组中的元素。
    • end
      1. 在该索引处结束提取原数组元素(从0开始)。
      2. slice会提取原数组中索引从beginend的所有元素(包含begin,但不包含end)。
  2. 用法:方法通起止索引截取数组中的元素,返回一个新的数组对象。原始数组不会被改变。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    let arr = [1, 2, 3, 4, 5];
    // start为正数,没有end
    console.log(arr.slice(1)); //[2,3,4,5]
    console.log(arr); //[1,2,3,4,5]

    let arr1 = [1, 2, 3, 4, 5];
    // start为正数,有end
    console.log(arr1.slice(1, 3)); //[2,3]
    console.log(arr1); //[1,2,3,4,5]

    let arr2 = [1, 2, 3, 4, 5];
    // 两个参数都是负数
    console.log(arr2.slice(-3, -1)); //[3,4]
    console.log(arr2); //[1,2,3,4,5]

join()方法

  1. 一个参数
    • eparator
      1. 指定一个字符串来分隔数组的每个元素。
      2. 默认为,
      3. 如果separator是空字符串"",则所有元素之间都没有任何字符。
  2. 用法:将一个数组的所有元素按指定分隔符连接成一个字符串并返回这个字符串,不改变原数组。
    1
    2
    3
    4
    let arr = [1, 3, 4];
    console.log(arr.join("")); // "134"
    console.log(arr.join("-")); // "1-3-4"
    // "1";

reverse() 方法

  1. 参数:无。
  2. 用法:方法将数组中元素的位置颠倒。改变原数组。
    1
    2
    3
    let arr = [1,2,3,4,5];
    console.log(arr.reverse()); // [5, 4, 3, 2, 1]
    console.log(arr) // [5, 4, 3, 2, 1]

concat()方法

  1. 参数:无。
  2. 用法:用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
    1
    2
    3
    4
    let arr = [1, 3, 4];
    let arr1 = [1, 2, "a"];
    console.log(arr.concat(arr1));
    // [1,3,4,1,2,"a"];

indexOf()方法

  1. 两个参数:
    • searchElement 要查找的元素。
    • fromIndex
      1. 开始查找的位置。默认为0
      2. -1代表数组中的最后一个元素,依次为起点往前查找。
  2. 用法:返回在数组中可以找到给定元素的第一个索引,如果不存在,则返回-1
    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.indexOf(1)); // 0
    console.log(arr.indexOf(5)); // -1

lastIndexOf()方法

  1. 两个参数:
  • searchElement要查找的元素。
  • fromIndex
    1. 从此位置开始逆向查找。默认为数组的长度减1,即整个数组都被查找。
    2. 如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。
    3. 即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回-1,即数组不会被查找。
  1. 用法:返回指定元素在数组中的最后一个的索引,如果不存在则返回-1。从数组的后面向前查找,从传参的索引处开始。
    1
    2
    3
    let arr = [1, 2, 3, 1];
    console.log(arr.lastIndexOf(1, 0)); // 3
    console.log(arr.lastIndexOf(1, 2)); // 0

toString()方法

  1. 参数:无。
  2. 用法:返回一个数组元素组成的字符串,以逗号分隔。不改变原数组。

    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.toString()); // "1,2,3"
    console.log(arr); // [1, 2, 3]

map()方法

  1. 两个参数:
    • callback接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. array,map方法被调用的数组。
    • thisArg
      1. 执行callback函数时使用的this值。
      2. 如果thisArg参数有值,则每次callback函数被调用的时候,this都会指向thisArg参数上的这个对象。如果省略了thisArg参数,或者赋值为nullundefined,则this指向全局对象。
  2. 用法:数组调用该方法,callback会循环遍历数组一次,最后返回一个每一次循环遍历处理后的结果组成的新数组。不会改变原有数组。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    let obj = {
    name: 'csz',
    say: function () {
    console.log(this.name);
    }
    }
    let arr = [1, 2];
    let map1 = arr.map(function (value, index, array) {
    console.log(value, index, array);
    this.say();
    return value = value + 2;
    }, obj);
    console.log(map1, arr);
    // 打印结果
    1 0 [1, 2]
    csz
    2 1 [1, 2]
    csz
    [3, 4] [1, 2]

    因为箭头函数内的this指向是保持不变的,所以当要使用thisArg参数时,不要使用箭头函数。

every()

  1. 两个参数:
    • callback用来测试每个元素的函数,接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. array,every方法被调用的数组。
      4. 遍历数组的每一个元素执行callback,只要有一个元素在执行callback的时候return falseevery方法停止执行返回false
    • hisArg执行callback时使用的this值。(使用方法用map()一致)
  2. 用法:方法测试数组的所有元素是否都通过了指定函数的测试。全部通过返回true, 否则返回false
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let arr = [1, 3, 5, 7, 9, 10];
    let arr1 = [1, 3, 5, 7];
    console.log(arr.every((v, i, array) => {
    return v % 2 !== 0;
    }));
    console.log(arr1.every((v, i, array) => {
    return v % 2 !== 0;
    }));
    // 打印结果
    false
    true

some()

  1. 两个参数:
    • callback用来测试每个元素的函数,接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. array,every方法被调用的数组。
      4. 遍历数组的每一个元素执行callback,只要有一个元素在执行callback的时候return trueevery方法停止执行返回true
    • thisArg执行callback时使用的this值。(使用方法用map()一致)
  2. 用法:方法测试数组中的某些元素是否通过由提供的函数实现的测试。有一个通过返回true, 全部不通过返回false
    1
    2
    3
    4
    5
    let arr = [1, 3, 5, 7, 9, 21, 2, 4, 6];
    console.log(arr.some((v, i, array) => {
    return v > 10;
    }));
    // true

filter()

  1. 两个参数:
    • callback用来测试每个元素的函数,接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. arrayfilter方法被调用的数组。
      4. 遍历数组的每一个元素执行callback,把满足条件的元素返回最后集合组成一个新的数组。
    • thisArg执行callback时使用的this值。(使用方法用map()一致)
  2. 方法:方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
    1
    2
    3
    4
    5
    6
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    let newArr = arr.filter((v, i, array) => {
    return v % 2 === 0;
    });
    console.log(newArr);
    // [2,4,6,8]

实例方法(ES6)

不管是通过字面量还是new Array亦或者是Array.of()创建的实例对象,它们的__proto__属性都是指向了Array的原型对象,就继承了原型对象上的属性和方法。

Array.prototype.

includes()方法

  1. 两个参数:
    • searchElement需要查找的元素值。-
    • fromIndex从该索引处开始查找searchElement。如果为负值,则按升序从array.length - fromIndex的索引开始搜索。默认为0
  2. 用法:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true,否则返回false
    1
    2
    3
    let arr = [1, 2, 3];
    console.log(arr.includes(1)); // true
    console.log(arr.includes(5)); // false

find()方法

  1. 两个参数:
    • callback用来测试每个元素的函数,接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. array,find方法被调用的数组。
      4. 遍历数组的每一个元素执行callback,返回第一个满足条件的元素。
    • thisArg执行callback时使用的this值。(使用方法用map()一致)
  2. 用法:方法返回数组中满足提供的测试函数的第一个元素的值。否则返回undefined
    1
    2
    3
    4
    5
    6
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    let newArr = arr.find((v, i, array) => {
    return v > 5;
    });
    console.log(newArr);
    // 6

findIndex()方法

  1. 两个参数:
    • callback用来测试每个元素的函数,接受3个参数。
      1. currentValue,数组中正在处理的当前元素。
      2. index,数组中正在处理的当前元素的索引。
      3. arrayfindIndex方法被调用的数组。
      4. 遍历数组的每一个元素执行callback,返回第一个满足条件的元素的索引。
    • thisArg执行callback时使用的this值。(使用方法用map()一致)
  2. 用法:方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1
    1
    2
    3
    4
    5
    6
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    let newArr = arr.findIndex((v, i, array) => {
    return v > 5;
    });
    console.log(newArr);
    // 5

fill()方法

方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。改变原数组。

  1. 三个参数:
    • start`用来填充数组元素的值。
    • start起始索引,默认值为0。
    • end终止索引,默认值为this.length
  2. 用法
    1
    2
    3
    4
    let arr = [1, 2, 3, 4, 5, 6];
    arr.fill("csz", 1, 4);
    console.log(arr);
    // [1, "csz", "csz", "csz", 5, 6]

还有几个方法相关介绍我还没有理的很清楚,这里先不贴了。等后续会加上…

----------本文结束感谢您的阅读-----------
谢谢打赏,好人一生平安