【JavaScript】标准库:Array对象

文章目录

  • [1 构造函数](#1 构造函数)
  • [2 静态方法](#2 静态方法)
    • [2.1 Array.isArray()](#2.1 Array.isArray())
  • [3 实例方法](#3 实例方法)
    • [3.1 valueOf(),toString()](#3.1 valueOf(),toString())
    • [3.2 push(),pop()](#3.2 push(),pop())
    • [3.3 shift(),unshift()](#3.3 shift(),unshift())
    • [3.4 join()](#3.4 join())
    • [3.5 concat()](#3.5 concat())
    • [3.6 reverse()](#3.6 reverse())
    • [3.7 slice()](#3.7 slice())
    • [3.8 splice()](#3.8 splice())
    • [3.9 sort()](#3.9 sort())
    • [3.10 map()](#3.10 map())
    • [3.11 forEach()](#3.11 forEach())
    • [3.12 filter()](#3.12 filter())
    • [3.13 some(),every()](#3.13 some(),every())
    • [3.14 reduce(),reduceRight()](#3.14 reduce(),reduceRight())
    • [3.15 indexOf(),lastIndexOf()](#3.15 indexOf(),lastIndexOf())
    • [3.16 链式使用](#3.16 链式使用)

1 构造函数

Array是 JavaScript 的原生对象,同时也是一个构造函数,可以用它生成新的数组。

javascript 复制代码
var arr = Array(2);
// 等同于
var arr = new Array(2);
arr.length // 2

考虑到语义性,以及与其他构造函数用法保持一致,建议总是加上new。

Array()构造函数不同的参数个数会导致不一致的行为。

javascript 复制代码
// 无参数时,返回一个空数组
new Array() // []

// 单个正整数参数,表示返回的新数组的长度
new Array(1) // [ empty ]
new Array(2) // [ empty x 2 ]

// 单个非数值(比如字符串、布尔值、对象等)作为参数,
// 则该参数是返回的新数组的成员
new Array('abc') // ['abc']
new Array([1]) // [Array[1]]

// 多参数时,所有参数都是返回的新数组的成员
new Array(1, 2) // [1, 2]
new Array('a', 'b', 'c') // ['a', 'b', 'c']

因此,不建议使用它生成新数组,直接使用数组字面量是更好的做法。

javascript 复制代码
var arr = [1, 2];

2 静态方法

2.1 Array.isArray()

Array.isArray方法返回一个布尔值,表示参数是否为数组。

javascript 复制代码
var arr = [1, 2, 3];

typeof arr // "object"
Array.isArray(arr) // true

3 实例方法

3.1 valueOf(),toString()

数组的valueOf方法返回数组本身。

javascript 复制代码
var arr = [1, 2, 3];
arr.valueOf() // [1, 2, 3]

数组的toString方法返回数组的字符串形式。

javascript 复制代码
var arr = [1, 2, 3];
arr.toString() // "1,2,3"

var arr = [1, 2, 3, [4, 5, 6]];
arr.toString() // "1,2,3,4,5,6"

3.2 push(),pop()

push方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度,该方法会改变原数组。

javascript 复制代码
var arr = [];

arr.push(1) // 1
arr.push('a') // 2
arr.push(true, {}) // 4
arr // [1, 'a', true, {}]

pop方法用于删除数组的最后一个元素,并返回该元素,该方法会改变原数组。

javascript 复制代码
var arr = ['a', 'b', 'c'];

arr.pop() // 'c'
arr // ['a', 'b']

[].pop() // undefined,对空数组使用pop()不报错。

3.3 shift(),unshift()

shift()方法用于删除数组的第一个元素,并返回该元素,该方法会改变原数组。

javascript 复制代码
var a = ['a', 'b', 'c'];

a.shift() // 'a'
a // ['b', 'c']

unshift()方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度,该方法会改变原数组。

javascript 复制代码
var a = ['a', 'b', 'c'];

a.unshift('x'); // 4
a // ['x', 'a', 'b', 'c']

unshift()方法可以接受多个参数,这些参数都会添加到目标数组头部。

javascript 复制代码
var arr = [ 'c', 'd' ];
arr.unshift('a', 'b') // 4
arr // [ 'a', 'b', 'c', 'd' ]

3.4 join()

join()方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回,默认用逗号分隔。

javascript 复制代码
var a = [1, 2, 3, 4];

a.join(' ') // '1 2 3 4'
a.join(' | ') // "1 | 2 | 3 | 4"
a.join() // "1,2,3,4"

如果数组成员是undefined或null或空位,会被转成空字符串。

javascript 复制代码
[undefined, null].join('#')
// '#'

['a',, 'b'].join('-')
// 'a--b'

通过call方法,这个方法也可以用于字符串或类似数组的对象。

javascript 复制代码
Array.prototype.join.call('hello', '-')
// "h-e-l-l-o"

var obj = { 0: 'a', 1: 'b', length: 2 };
Array.prototype.join.call(obj, '-')
// 'a-b'

3.5 concat()

concat方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。

javascript 复制代码
['hello'].concat(['world'])
// ["hello", "world"]

['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]

[].concat({a: 1}, {b: 2})
// [{ a: 1 }, { b: 2 }]

[2].concat({a: 1})
// [2, {a: 1}]

[1, 2, 3].concat(4, 5, 6) // 其他类型的值作为参数
// [1, 2, 3, 4, 5, 6]

3.6 reverse()

reverse方法用于颠倒排列数组元素,返回改变后的数组,该方法将改变原数组。

javascript 复制代码
var a = ['a', 'b', 'c'];

a.reverse() // ["c", "b", "a"]
a // ["c", "b", "a"]

3.7 slice()

slice()方法用于提取目标数组的一部分,返回一个新数组,原数组不变。

slice(起始位置,终止位置不包括),相当于[起始位置,终止位置)。

javascript 复制代码
var a = ['a', 'b', 'c'];

a.slice(0) // ["a", "b", "c"]
a.slice(1) // ["b", "c"]
a.slice(1, 2) // ["b"]
a.slice(2, 6) // ["c"]
a.slice() // ["a", "b", "c"]

如果slice()方法的参数是负数,则表示倒数计算的位置。

javascript 复制代码
var a = ['a', 'b', 'c'];
a.slice(-2) // ["b", "c"]
a.slice(-2, -1) // ["b"]

如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。

javascript 复制代码
var a = ['a', 'b', 'c'];
a.slice(4) // []
a.slice(2, 1) // []

slice()方法的一个重要应用,是将类似数组的对象转为真正的数组。

javascript 复制代码
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }) // ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div"));
Array.prototype.slice.call(arguments);

3.8 splice()

splice()方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素,该方法会改变原数组。

javascript 复制代码
arr.splice(start, count, addElement1, addElement2, ...);

splice的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。

javascript 复制代码
// 从原数组4号位置,删除了两个数组成员。
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(4, 2) // ["e", "f"]
a // ["a", "b", "c", "d"]

// 上面代码除了删除成员,还插入了两个新成员。
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(4, 2, 1, 2) // ["e", "f"]
a // ["a", "b", "c", "d", 1, 2]

起始位置如果是负数,就表示从倒数位置开始删除。

javascript 复制代码
// 从倒数第四个位置c开始删除两个成员。
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(-4, 2) // ["c", "d"]

如果只是单纯地插入元素,splice方法的第二个参数可以设为0。

javascript 复制代码
var a = [1, 1, 1];

a.splice(1, 0, 2) // []
a // [1, 2, 1, 1]

如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。

javascript 复制代码
var a = [1, 2, 3, 4];
a.splice(2) // [3, 4]
a // [1, 2]

3.9 sort()

sort方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。

javascript 复制代码
['d', 'c', 'b', 'a'].sort()
// ['a', 'b', 'c', 'd']

[4, 3, 2, 1].sort()
// [1, 2, 3, 4]

/*
	sort()方法不是按照大小排序,而是按照字典顺序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较。
*/
[11, 101].sort()
// [101, 11]

[10111, 1101, 111].sort()
// [10111, 1101, 111]

如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数。

javascript 复制代码
[10111, 1101, 111].sort(function (a, b) {
  return a - b; // 大于0,二者交换
})
// [111, 1101, 10111]

[
  { name: "张三", age: 30 },
  { name: "李四", age: 24 },
  { name: "王五", age: 28  }
].sort(function (o1, o2) {
  return o1.age - o2.age;
})
// [
//   { name: "李四", age: 24 },
//   { name: "王五", age: 28  },
//   { name: "张三", age: 30 }
// ]

3.10 map()

map()方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

javascript 复制代码
var numbers = [1, 2, 3];

numbers.map(function (n) {
  return n + 1;
});
// [2, 3, 4]

numbers
// [1, 2, 3]

map()方法接受一个函数作为参数。该函数调用时,map()方法向它传入三个参数:当前成员、当前位置和数组本身。

javascript 复制代码
[1, 2, 3].map(function(elem, index, arr) {
  return elem * index;
});
// [0, 2, 6]

map()方法还可以接受第二个参数,用来绑定回调函数内部的this变量。

javascript 复制代码
var arr = ['a', 'b', 'c'];

[1, 2].map(function (e) {
  return this[e];
}, arr)
// ['b', 'c']

如果数组有空位,map()方法的回调函数在这个位置不会执行,会跳过数组的空位。

javascript 复制代码
var f = function (n) { return 'a' };

// map()方法不会跳过undefined和null
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]

3.11 forEach()

forEach()方法与map()方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach()方法不返回值,只用来操作数据。如果数组遍历的目的是为了得到返回值,那么使用map()方法,否则使用forEach()方法。

forEach()的用法与map()方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。

javascript 复制代码
function log(element, index, array) {
  console.log('[' + index + '] = ' + element);
}

[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9

forEach()方法也可以接受第二个参数,绑定参数函数的this变量。

javascript 复制代码
var out = [];

[1, 2, 3].forEach(function(elem) {
  this.push(elem * elem);
}, out);

out // [1, 4, 9]

forEach()方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用for循环。

forEach()方法也会跳过数组的空位,不会跳过undefined和null。

3.12 filter()

filter()方法用于过滤数组成员,满足条件的成员组成一个新数组返回。

它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回,该方法不会改变原数组。

javascript 复制代码
[1, 2, 3, 4, 5].filter(function (elem) {
  return (elem > 3);
})
// [4, 5]

var arr = [0, 1, 'a', false];

arr.filter(Boolean)
// [1, "a"]

filter()方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。

javascript 复制代码
[1, 2, 3, 4, 5].filter(function (elem, index, arr) {
  return index % 2 === 0;
});
// [1, 3, 5]

filter()方法还可以接受第二个参数,用来绑定参数函数内部的this变量。

javascript 复制代码
var obj = { MAX: 3 };
var myFilter = function (item) {
  if (item > this.MAX) return true;
};

var arr = [2, 8, 3, 4, 1, 3, 2, 9];
arr.filter(myFilter, obj) // [8, 4, 9]

3.13 some(),every()

返回一个布尔值,表示判断数组成员是否符合某种条件。

它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。

some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false。

javascript 复制代码
var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
  return elem >= 3;
});
// true

every方法是所有成员的返回值都是true,整个every方法才返回true,否则返回false。

javascript 复制代码
var arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
  return elem >= 3;
});
// false

对于空数组,some方法返回false,every方法返回true,回调函数都不会执行。

javascript 复制代码
function isEven(x) { return x % 2 === 0 }

[].some(isEven) // false
[].every(isEven) // true

some和every方法还可以接受第二个参数,用来绑定参数函数内部的this变量。

3.14 reduce(),reduceRight()

reduce()方法和reduceRight()方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce()是从左到右处理(从第一个成员到最后一个成员),reduceRight()则是从右到左(从最后一个成员到第一个成员),其他完全一样。

javascript 复制代码
[1, 2, 3, 4, 5].reduce(function (a, b) {
  console.log(a, b);
  return a + b;
})
// a b
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15

reduce()方法和reduceRight()方法的第一个参数都是一个函数。该函数接受以下四个参数。这四个参数之中,只有前两个是必须的,后两个则是可选的。

  • 累积变量。第一次执行时,默认为数组的第一个成员;以后每次执行时,都是上一轮的返回值。
  • 当前变量。第一次执行时,默认为数组的第二个成员;以后每次执行时,都是下一个成员。
  • 当前位置。一个整数,表示第二个参数(当前变量)的位置,默认为1。
  • 原数组。

如果要对累积变量指定初值,可以把它放在reduce()方法和reduceRight()方法的第二个参数。

javascript 复制代码
[1, 2, 3, 4, 5].reduce(function (a, b) {
  return a + b;
}, 10);
// 25,数组从10开始累加
javascript 复制代码
function subtract(prev, cur) {
  return prev - cur;
}

[3, 2, 1].reduce(subtract) // 0
[3, 2, 1].reduceRight(subtract) // -4

3.15 indexOf(),lastIndexOf()

indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。

javascript 复制代码
var a = ['a', 'b', 'c'];

a.indexOf('b') // 1
a.indexOf('y') // -1

indexOf方法还可以接受第二个参数,表示搜索的开始位置。

javascript 复制代码
['a', 'b', 'c'].indexOf('a', 1) // -1

lastIndexOf方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。

javascript 复制代码
var a = [2, 5, 9, 2];
a.lastIndexOf(2) // 3
a.lastIndexOf(7) // -1

这两个方法不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN。因为这两个方法内部,使用严格相等运算符(===)进行比较,而NaN是唯一一个不等于自身的值。

javascript 复制代码
[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1

3.16 链式使用

上面这些数组方法之中,有不少返回的还是数组,所以可以链式使用。

javascript 复制代码
var users = [
  {name: 'tom', email: 'tom@example.com'},
  {name: 'peter', email: 'peter@example.com'}
];

users
.map(function (user) {
  return user.email;
})
.filter(function (email) {
  return /^t/.test(email);
})
.forEach(function (email) {
  console.log(email);
});
// "tom@example.com"
相关推荐
卸任12 小时前
Vibe coding工具使用心得
前端·ai编程
brien912 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance13 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M13 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写13 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李13 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易13 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding13 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马13 小时前
前沿视界
前端
kyriewen13 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员