JS数组知识点
Array数组
Array类型是JavaScript最常用的类型,而且JavaScript中的Array类型和其他语言中的数组有着很大的区别。虽然数组都是有序排列,但JavaScript中的数组每个元素可以保存任何类型,JavaScript中数组的大小也是可以调整的。
和java中map类似,数组底层是map,key是数字,value可以使obj,任何类型
创建数组
创建Array类型有两种方式:第一种是new运算符,第二种是字面量。
- 使用new关键字创建数组
var cat = new Array(); //创建了一个数组
var cat = new Array(3); //创建一个包含3个元素的数组
var cat = new Array("big","red","2");
Array()是构造函数,一般来说使用new Array()来返回新创建并被初始化了的数组。当它做为函数调用时,跟它使用new 运算符调用一样!
第一个没有参数,就返回一个空数组。
第二个一个参数,那么这个参数是整数就表示你想要创建的数组的长度length,返回一个长度为指定参数的空位数组。 比如:
var cat = new Array(3); //[,,,]
如果这一个参数是字符串,他就创建了一个有一个元素的数组
var arr = new Array("3") // arr = ["3"]
第三个多个参数(最少2个),这些参数就表示数组中的元素,返回一个以这些参数为元素的数组。
- 使用字面量创建数组
var cat = []; //创建了一个数组
var cat = ["big","red","2"];//创建一个数组并分配好了元素
数组的属性
constructor
- 返回对创建此对象的数组函数的引用
var arr = [];
console.log(arr.constructor); // Array()
length
- 要取得Array的长度,直接访问length属性
var arr = [1, 2, 3.14, 'Hello', null, true];
arr.length; // 6
请注意,直接给Array的length赋一个新的值会导致Array大小的变化:
var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, empty x 3]empty没有占空间,undefinded申请有空间,没有赋值
arr.length = 2;
arr; // arr变为[1, 2]
Array可以通过索引把对应的元素修改为新的值,因此,对Array的索引进行赋值会直接修改这个Array:
var arr = ['A', 'B', 'C'];
arr[1] = 99;
arr; // arr现在变为['A', 99, 'C']
请注意,如果通过索引赋值时,索引超过了范围,同样会引起Array大小的变化:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']
大多数其他编程语言不允许直接改变数组的大小,越界访问索引会报错。然而,JavaScript的Array却不会有任何错误。在编写代码时,不建议直接修改Array的大小,访问索引时要确保索引不会越界。索引为负数不会引起长度的变化,验证出数组的底层是map。
typeof arr // object
arr instanceof Array // true
数组中的方法
1.indexOf(), lastIndexOf
- 与String类似,Array也可以通过indexOf()来搜索一个指定的元素的位置,
传具体的对象
indexOf(元素,起始位置)
var arr = [10, 20, '30', 'xyz'];
arr.indexOf(10); // 元素10的索引为0
arr.indexOf(20); // 元素20的索引为1
arr.indexOf(30); // 元素30没有找到,返回-1
arr.indexOf('30'); // 元素'30'的索引为2
arr.indexOf('30',3); //从下标3处查找'30'
注意了,数字30和字符串’30’是不同的元素
2.toString()
- 将数组内容以字符串形式输出;
var arrs = [1,2];
console.log(arrs.toString()); // 1,2
3.concat()
- 该方法用于连接2个或者多个数组。
语法:arrayObject.concat(array1,array2,…arrayx,任意元素(放数组自动展开));
连接多个数组,使用逗号隔开;
var arr1 = [1,2,3],
arr2 = [4,5,6],
arr3 = [7,8,9,1,2,3];
console.log(arr1.concat(arr2,arr3)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]
console.log(arr1); // [1,2,3]
console.log(arr2); // [4,5,6]
console.log(arr3); // [7,8,9,1,2,3]
请注意,concat()方法并没有修改当前Array,而是返回了一个新的Array。
- 实际上,concat()方法可以接收任意个元素和Array,并且自动把Array拆开,然后全部添加到新的Array里:
var arr = ['A', 'B', 'C'];
arr.concat(1, 2, [3, 4]); // ['A', 'B', 'C', 1, 2, 3, 4]
4.join()
- 该方法是把数组中的所有元素放入一个字符串中,元素通过指定的链接符拼接成字符串。
语法如下:arrayObject.join(字符串);
字符串: 元素通过指定的链接符拼接成字符串,如果省略该参数,则会使用逗号作为链接符。如下代码演示:
var arrs = [];
arrs[0] = "aa";
arrs[1] = "bb";
arrs[2] = "cc";
console.log(arrs.join()); // aa,bb,cc
console.log(arrs.join("/")); // aa/bb/cc
console.log(arrs.join("-")); // aa-bb-cc
- 如果Array的元素不是字符串,将自动转换为字符串后再连接。
var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // 'A-B-C-1-2-3'
5.push()
- 该方法是向数组末尾添加一个或者多个元素,并返回新的长度。
基本语法:arrayObject.push(newElem1,newElem2,…newElemX);
var arrs = [1,2,3];
arrs.push(4);
console.log(arrs); // [1,2,3,4]
arrs.push(5,6);
console.log(arrs); // [1,2,3,4,5,6]
6.pop()
- 该方法删除数组的最后一个元素,把数组的长度减1(改变原数组),并且返回它被删除元素的值,如果数组变为空,则该方法不改变数组,返回undefine值。
var arrs = [1,2,3,4];
console.log(arrs.pop()); // 4
console.log(arrs); // [1,2,3]
7.shift()(栈)
- 该方法用于把数组的第一个元素从其中删除,并返回被删除的值。如果数组是空的,shift方法将不进行任何操作,返回undefined的值。
var arrs = [1,2,3,4];
console.log(arrs.shift());// 1
console.log(arrs); // [2,3,4]
var arrs2 = [];
console.log(arrs2.shift()); // undefined
8.unshift()
- 该方法是向数组的开头添加一个或者更多元素,并返回新的长度。带优先级的用来插队
var arrs = [1,2];
arrs.unshift(3);
console.log(arrs); //[3, 1, 2]
9.sort([sortby:function(a,b) {}])(稳定排序)
- 该方法是对数组的元素进行排序;sortby参数规定排序顺序,且必须是函数。如果该方法没有使用参数,则是按字母的字符编码的顺序进行排序。
- 如果想按其他标准进行排序,就需要提供比较函数,该函数比较2个值,然后返回一个用于说明这2个值的相对顺序的数字,比如比较a与b,返回值如下:返回值大于0,交换,其他不变
若a小于b,在排序后的数组中a应该出现在b之前,则返回一个小于0的值。
若a等于b,在排序后的数组中 a等于b 则返回0;
若a大于b,则返回一个大于0的值;
var arrs = ["tugenhua","longen","alibaba"];
console.log(arrs.sort()); // ["alibaba", "longen", "tugenhua"]
var arrs2 = ["15","5","8","12"];
console.log(arrs2.sort(function(a,b){
return a - b; // ["5", "8", "12", "15"]
}));
10.reverse()
- 该方法用于反转数组中元素的顺序,改变原数组;
var arrs = [1,2,3,4];
console.log(arrs.reverse());// [4,3,2,1]
console.log(arrs); // [4,3,2,1]
11.splice()
- 该方法用于插入,删除和替换数组的元素;
基本语法:Array.splice(index,howmany,element1,…elementX);
Index参数:【必填】是从何处添加/删除元素,该参数是开始插入或删除数组元素的下标,必须是数字;
Howmany: 【可选】应该删除多少个元素,必须是数字,也可以是0,如果未设定该参数,则删除从index开始到原数组结尾的所有元素,返回被删除的值;
Element1: 【可选】规定要添加到数组的新元素,从index所指的下标处开始插入;
ElementX: 【可选】 可向数组中添加若干个元素;
// 假如原数组如下
var arrs = [1,2,3,4,5,6];
// 先向数组的第二个位置中添加一个元素8;
arrs.splice(1,0,8);返回[],因为没有删除任何元素
console.log(arrs); // [1, 8, 2, 3, 4, 5, 6]
// 接着从arrs数组中删除一个元素2,3
arrs.splice(2,2);// 返回删除的元素 [2,3]
console.log(arrs); // [1, 8, 4, 5, 6]
// 再接着从arrs数组中替换一个元素8 使他变为10;如下代码:
arrs.splice(1,1,10);返回删除的元素 [8]
console.log(arrs); // [1, 10, 4, 5, 6]
//添加
arrs.splice(5,0,12,22,32,42,52);//返回[]
console.log(arrs); // [1, 10, 4, 5, 6, 12, 22, 32, 42, 52]
12.slice()(圆)
- 该方法是从已有的数组中返回指定的元素,返回的元素组成新的数组,对应String的substring()版本,它用来截取数组的元素
基本语法:arrs.slice(start,end);
start参数【必须】从何处开始选取(包括start),如果是负数,那么会从尾部选取,比如-1代表最后一个元素,-2代表倒数第二个元素,以此类推。
End参数【可选】规定是从何处结束选取(不包括end),如果没有指定该参数,那么数组会包含从start开始到数组结束的所有元素,如果该参数是负数的话,那么它规定的是从数组尾部开始算起的元素。
var arrs2 = [1,2,3];
console.log(arrs2.slice(1)); // [2,3]
console.log(arrs2.slice(0,1));// [1]
console.log(arrs2.slice(1,-1)); // [2]
console.log(arrs2.slice(2,-1)); // []
console.log(arrs2.slice(0)); // [1,2,3]
如果不给slice()传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容易地复制一个Array:
var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var aCopy = arr.slice();
aCopy; // ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
aCopy === arr; // false
Javascript不能直接用==
或者===
来判断两个不同内存的数组是否相等,无论是相等还是全等都不行,所以上面最后一行代码会返回false
要判断JS中的两个数组是否相同,需要先将数组转换为字符串,再作比较。
console.log(arr.toString()=== aCopy.toString());//true
如果要比较两个数组是否有相同的元素,即两个数组所有元素都相同,但元素的顺序不一定一致。只就需要先将数组进行排序,再比较两个数组是否相等。(有风险)
var arr1 = ["hel,lo"]
undefined
var arr2 = ["hel","lo"]
undefined
arr1.toString() == arr2.toString() // true
其实是不相等的
arr1 = [1,'3','hel,lo','1221','adsa2'];
arr2 = ['3',1,'adsa2','hel,lo','1221'];
console.log(arr1.splice().sort().toString()== arr2.splice().sort().toString());//true
数组的扩展
扩展运算符
含义
- 扩展运算符(spread)是三个点(…)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(...[1, 2, 3])实参
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
- 该运算符主要用于函数调用。
function push(array, ...items) {形参
array.push(...items);
}
arr = [];
arr2 = [1,2,3,4,5];
push(arr,...arr2);
console.log(arr);//[1,2,3,4,5]
function add(x, y) {
return x + y;
}
const numbers = [4, 38];
add(...numbers); // 42
上面代码中,array.push(…items)和add(…numbers)这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。
- 扩展运算符与正常的函数参数可以结合使用,非常灵活。
function f(v, w, x, y, z) {
return w
}
var arr = [0, 1];
f(-1, ...arr, 2, ...[3]); // 0
- 扩展运算符后面还可以放置表达式。
var arr = [
...(2 > 0 ? ['a'] : []),
'b',
]; //["a","b"]
- 如果扩展运算符后面是一个空数组,则不产生任何效果。
[...[], 1]; // [1]
数组拷贝:部分拷贝(splice,slice),全拷贝(slice, …),扩大拷贝(… ,concat)
替代数组的 apply 方法
- 由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。
function f(x, y, z) {
return y
}
let args = [0, 1, 2];
f.apply(null, args); //1 null是上下文,这里没有
// ES6的写法
function f(x, y, z) {
return z
}
let arrs = [0, 1, 2];
f(...arrs); // 2
- 下面是扩展运算符取代apply方法的一个实际的例子,应用Math.max方法,简化求出一个数组最大元素的写法。
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
上面代码中,由于 JavaScript不提供求数组最大元素的函数,所以只能套用Math.max函数,将数组转为一个参数序列,然后求最大值。有了扩展运算符以后,就可以直接用Math.max了。
- 另一个例子是通过push函数,将一个数组添加到另一个数组的尾部。
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);调用原型链上的方法
// ES6 的写法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);
上面代码的 ES5 写法中,push方法的参数不能是数组,所以只好通过apply方法变通使用push方法。有了扩展运算符,就可以直接将数组传入push方法。
扩展运算符的应用
- 复制数组
数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。
var= [1, 2];
var a2 = a1;
a2[0] = 2;
a1 // [2, 2]
上面代码中,a2并不是a1的克隆,而是指向同一份数据的另一个指针。修改a2,会直接导致a1的变化。
var a1 = [1, 2];
var a2 = a1.concat();
a2[0] = 2; a2 = [2,2]
a1 = [1, 2]
上面代码中,a1会返回原数组的克隆,再修改a2就不会对a1产生影响。
扩展运算符提供了复制数组的简便写法。
var a1 = [1, 2];
// 写法一
var a2 = [...a1];
// 写法二
var [...a2] = a1;
上面的两种写法,a2都是a1的克隆。
- 合并数组
扩展运算符提供了数组合并的新写法。
[1, 2].concat(more)
// ES6
[1, 2, ...more]
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5的合并数组
arr1.concat(arr2, arr3); // [ 'a', 'b', 'c', 'd', 'e' ]
// ES6的合并数组
[...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]
- 与解构赋值结合(多用于对象)
扩展运算符可以与解构赋值结合起来,用于生成数组。
什么是解构赋值:
语法上就是赋值的作用。
解构:左边一种结构,右边一种结构,左右一一对应进行赋值。
var [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
var [first, ...rest] = [];
first // undefined
rest // []空的
var [first, ...rest] = ["foo"];
first // "foo"
rest // []空的
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
const [...butLast, last] = [1, 2, 3, 4, 5]; // 报错
const [first, ...middle, last] = [1, 2, 3, 4, 5]; // 报错
- 字符串
扩展运算符还可以将字符串转为真正的数组。
[...'hello']; // [ "h", "e", "l", "l", "o" ]