# 数组
# 创建数组
数组的每一项可以用来保存任何类型的数据,数组的大小可以动态改变。本质上是对象
var colors = new Array(); // 创建一个空数组,括号里可以填数组长度
var colors = []; // 创建一个空数组
var colors = ["red", "blue", "green"]; // 创建一个 3 项的数组
console.log(colors.toString());
console.log(colors.valueOf());
console.log(colors); // 都返回的是以逗号分割的字符串的形式返回数组项
注意
如果数组中的某一项值是 null 或 undefined,那么该值在 toString()
、valueOf()
、toLocalString()
和 join()
方法中返回的是空字符串
如果给 length
赋值可能会导致数组截断,实际开发中不要给 length
赋值,数组可以添加属性,但是并不添加到数组长度内
&
下标不连续的叫做稀松数组
检测是否为数组:Array.isArray(colors)
,返回 Boolean 类型,具体实现:
var isArray = Function.isArray || function (o) {
return typeof o === 'object' && Object.prototype.toString.call(o) === '[Object Array]'
}
# 数组元素的读写
数组通过 []
操作符即可访问和写入一个元素,数组也是对象,使用 []
访问时就像用 []
访问对象的属性一样
区分数组的索引和对象的属性名:所有的索引都是属性名,但只有 0 ~ 2^32^ - 2 之间的整数属性名才是索引
var arr = [1, 3, 5]
arr[-1.23] = true // 给数组添加一个属性名为 -1.23 的元素
console.log(arr) // [1, 3, 5, -1.23: true]
数组的索引是对象的属性名的一种特殊形式,这意味着 JavaScript 中没有数组“越界”错误的概念,当访问了不存在的属性时只会得到 undefined
# 数组的遍历
遍历数组有以下方法:
- for 循环
- for/in 循环
for/in
循环:循环每次将一个可枚举的属性名(包括数组索引)赋值给循环变量,不存在的索引将不会遍历到:
for (var index in array) {
// for/in 循环会枚举继承的属性名
// 每一轮循环需要判断是否是继承的属性
if (!array.hasOwnProperty(index)) {
continue
}
var value = array[index]
}
&
for/in 循环可以以不同的顺序遍历对象的属性,如果程序依赖于遍历的顺序就需要用普通的 for 循环
数组的长度应该是在遍历之前就应该查询出来,而不是每一次循环都要查询
# 数组的方法
# 栈方法
push()
:可以接收任意数量的参数,并把它们逐一添加到数组末尾,并返回修改后数组的长度。pop()
:删除数组最后一项,将数组的长度减 1,然后返回被删除的项。
# 队列方法
shift()
:删除数组中的第一项并返回该项,同时将数组的长度减 1unshift()
:可以在数组前端添加任意个项并返回数组的长度
push
和pop
可以用来模拟栈结构push
和shift
用来模拟队列结构
# 重排序方法
reverse()
:对数组进行反转sort()
:默认升序,调用每一项的toString()
方法,然后比较得到的字符串。可以接收一个比较函数作为参数
colors.sort(function () {
// 如果第一个参数小,返回一个负数
// 如果第一个参数大,返回一个整数
// 两者相等则返回 0
return a - b
});
# 数组的操作方法
splice()
删除(增加)指定位置和数量的元素- 删除:
arr.splice(3, 3)
从数组索引3开始删除3个元素,如果省略第二个参数则一直删除到数组结尾 - 增加:
a.rrsplice(3, 0, 1, 2, 3)
第三个参数以及后面的就是要添加到数组里面的值,如果索引越界,按照边界值处理
- 删除:
concat()
:不影响原数组- 复制当前数组并返回副本,如果参数是一个或多个数组,则把它的每一项都添加到结果数组中,如果参数不是数组,就直接添加到数组末尾
- 如果参数是数组中嵌套了数组,则会把嵌套的数据原封不动的当作一个元素添加进去
slice()
:不会影响原数组arr.slice(起始位置下标, 结束位置下标)
:返回包含起始位置但不包含结束位置的项得到一个新数组,如果只有一个参数,则返回从指定位置到数组末尾的所有项arr.slice(-3, -1)
:如果是负数,则从末尾计算。表示从倒数第三个到倒数第一个但不包括倒数第一个。- 如果不写结束下标就直接取到末尾
- 如果不传任何参数,默认将数组中的元素放到一个新的数组中原样返回
fill()
:arr.fill(数据)
:将数据的所有项,填充为指定的数据arr.fill(数据, 开始下标)
:将数组从开始下标到数组末尾填充为指定数据arr.fill(数据,开始下标, 结束下标)
:将数组从开始下标到结束下标(取不到)填充为指定数据
indexOf(数据)
:从数组的开头开始查找传进去的数据,返回的是查找的项在数组中第一次出现的位置,必须是严格相等的,如果没有找到则返回 -1lastIndexOf(数据)
:从数组的末尾开始查找,返回的也是第一次找到该数据的位置
find() 和 fliter() 的区别:
- find:返回通过测试的(函数内判断)数组的第一个元素,返回的是单个值
- fliter:创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
# 数组的本质
- 数组的本质是对象(引用类型),在数组中存放的是地址
- 复制一个数组(新创建了一个对象)
var arr2 = arr1.slice();
//这个arr2就是一个新的对象
- 可以利用数组实现斐波那契数列
var a = [];
a[0] = 1;
a[1] = 1;
for (let i = 2; i < 10; i++) {
a[i] = a[i - 1] + a[i - 2];
}
for (let i = 0; i < 10; i++) {
console.log(a[i]);
}
# 真数组与伪数组转换
真数组转成伪数组
// 把对象转成了伪数组
let arr = [1, 3, 5, 7, 9]
let obj = {}
;[].push.apply(obj, arr)
所做的操作如下:
- 通过
[].push
找到数组中的push
方法 - 调用
apply()
方法使 this 指向 obj - 将实参 arr 中的数据取出依次调用
push
方法加入到 obj 中
伪数组转成真数组
let obj = {
0: 'hhh',
1: 'eee',
length: 2
}
let arr = []
;[].push.apply(arr, obj) // 该方法在 IE8 及以下不支持
let arr2 = [].slice.call(obj) // 实际开发中使用这个方法
# 数组去重
- 利用 Set 数据结构
Array.from
方法
;[...new Set([1, 3, 4, 4, 4, 5, 5])]
Array.from(new Set([1, 3, 4, 4, 4, 5, 5]))
# 多维数组
数组是一个对象,里面可以存储任何类型的值,用数组嵌套数组可以实现多维数组
var a = [];
a[0] = ['a', 'b', 'c'];
a[1] = ['d', 'e', 'f'];
a[2] = ['g', 'h', 'i'];
// 输出数组
for (let i = 0; i < a.length; i++) {
for (let j = 0; j < a[i].length; j++) {
console.log(a[i][j]);
}
}
# 数组方法参考
方法名 | 描述 |
---|---|
concat | 连接 2 个或更多数组,并返回结果 |
every | 对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true |
filter | 对数组中的每一项运行给定函数,返回给定函数会返回 true 的项组成的数组 |
forEach | 对数组中的每一项运行给定函数,没有返回值(参数:数组元素,[索引,数组]) |
join | 将所有的数组元素连接成一个字符串 |
indexOf | 返回第一个与给定参数相等的数组元素的索引,没有找到则返回-1 |
lastIndexOf | 返回指定参数在调用该方法的字符串中最后出现的位置,没有则返回-1 |
map | 对数组中的每一项运行给定函数,返回一个数组,这个数组是由每次函数执行之后的结果组成 |
reverse | 反转元素顺序 |
slice | 传入索引值,返回一个指定索引范围内的新数组,如果不传默认将原数组组成新数组返回 |
some | 对数组中的每一项运行给定函数,如果任一项返回true,则返回true |
sort | 按照字母顺序对数组排序,可以传递参数指定排序方法 |
toString | 将数组作为字符串返回 |
valueOf | 将数组作为字符串返回 |