数组与集合
数组与集合
Array
创建构造
在 JavaScript 多种方式创建数组,可以利用构造函数与字面量等:
// 无参构造函数,创建一空数组
const a1 = new Array();
// 一个数字参数构造函数,指定数组长度
const a2 = new Array(5);
// 带有初始化数据的构造函数,创建数组并初始化参数数据
const a3 = new Array(4, "hello", new Date());
// 使用方括号,创建空数组,等同于调用无参构造函数
const a4 = [];
// 使用中括号,并传入初始化数据,等同于调用调用带有初始化数据的构造函数
const a5 = [10];
值得一提的是,在使用构造函数创建数组时如果传入一个数字参数,则会创建一个长度为参数的数组,如果传入多个,则创建一个数组,参数作为初始化数据加到数组中:
const a1 = new Array(5);
console.log(a1.length); //5
console.log(a1); //[] ,数组是空的
const a2 = new Array(5, 6);
console.log(a2.length); // 2
console.log(a2); // [5,6]
索引遍历
数组的值可以通过自然数索引访问进行读写操作,下标也可以是一个得出非负整数的变量或表达式:
const a1 = [1, 2, 3, 4];
console.log(a1[0]); //1
const i = 1;
console.log(a1[i]); //2
console.log(a1[++i]); //3
这样我们可以看出所有的索引都是属性名,但只有自然数(有最大值)才是索引,一般我们在使用数组的时候不会出现数组越界错误也正是因为此,数组的索引可以不是连续的,访问 index 不存在的元素的时候返回 undefined。
const a = new Array(1, 2, 3);
a[100] = 100;
console.log(a.length); //101
console.log(a[3]); //undefined
console.log(a[99]); //undefined
console.log(a[100]);
100;
添加与删除
栈方法
pop 和 push 能够让我们使用堆栈那样先入后出使用数组。
const a = new Array(1, 2, 3);
a.push(4);
console.log(a); //[1, 2, 3, 4]
console.log(a.length); //4
console.log(a.pop(a)); //4
console.log(a); //[1, 2, 3]
console.log(a.length); //3
队列方法
shift 方法可以删除数组 index 最小元素,并使后面元素 index 都减一,length 也减一,这样使用 shift/push 就可以模拟队列了,当然与 shift 方法对应的有一个 unshift 方法,用于向数组头部添加一个元素。
const a = new Array(1, 2, 3);
a.unshift(4);
console.log(a); //[4, 1, 2, 3]
console.log(a.length); //4
console.log(a.shift(a)); //4
console.log(a); //[1, 2, 3]
console.log(a.length); //3
slice
JavaScript 提供了一个 splice 方法用于一次性解决数组添加、删除(这两种方法一结合就可以达到替换效果),方法有三个参数:开始索引,删除元素的位移,插入的新元素,当然也可以写多个。
splice 方法返回一个由删除元素组成的新数组,没有删除则返回空数组:
const a = new Array(1, 2, 3, 4, 5);
console.log(a.splice(1, 3)); //[2, 3, 4]
console.log(a.length); //2
console.log(a); //[1,5]
只要方法第二个参数,也就是删除动作执行的次数设为 0,第三个参数及以后填写要插入内容就 splice 就能执行插入操作,而如果第二个参数不为 0 则变成了先在该位置删除再插入,也就是替换效果。
const a = new Array(1, 2, 3, 4, 5);
a.splice(1, 0, 9, 99, 999);
console.log(a.length); //8
console.log(a); //[1, 9, 99, 999, 2, 3, 4, 5]
a.splice(1, 3, 8, 88, 888);
console.log(a.length); //8
console.log(a); //[1, 8, 88, 888, 2, 3, 4, 5]
其他方法
join(char)
作用是把数组元素(对象调用其 toString()方法)使用参数作为连接符连接成一字符串:
const a = new Array(1, 2, 3, 4, 5);
console.log(a.join(",")); //1,2,3,4,5
console.log(a.join(" ")); //1 2 3 4 5
Transform | 转化
map
// Native
const array1 = [1, 2, 3];
const array2 = array1.map(function(value, index) {
return value * 2;
});
console.log(array2);
// output: [2, 4, 6]
reduce
const array = [0, 1, 2, 3, 4];
const result = array.reduce(function(
previousValue,
currentValue,
currentIndex,
array
) {
return previousValue + currentValue;
});
console.log(result); // output: 10 //reduceRight,正好方向相反
const array = [0, 1, 2, 3, 4];
const result = array.reduceRight(function(
previousValue,
currentValue,
currentIndex,
array
) {
return previousValue - currentValue;
});
console.log(result); // output: -2
filter
// Native
function isBigEnough(value) {
return value >= 10;
}
const array = [12, 5, 8, 130, 44];
const filtered = array.filter(isBigEnough);
console.log(filtered);
// output: [12, 130, 44]
sort
sort 方法用于对数组进行排序,当没有参数的时候会按字母表升序排序,如果含有 undefined 会被排到最后面,对象元素则会调用其 toString 方法,如果想按照自己定义方式排序,可以传一个排序方法进去,很典型的策略模式,同样 sort 会改变原数组。
const a = new Array(7, 8, 9, 10, 11);
a.sort(function(v1, v2) {
return v1 - v2;
});
console.log(a); //[7, 8, 9, 10, 11]
sort 内部使用快速排序,每次比较两个元素大小的时候如果没有参数,则直接判断字母表,如果有参数,则把正在比较的两个参数传入自定义方法并调用(正在比较的两个数会传给自定义方法的 v1、v2),如果返回值大于 0 表示 v1>v2
,如果等于 0,表示 v1=v2
,如果小于 0,表示 v1<v2
。
distinct
const array = [
{ id: 123, value: "value1", name: "Name1" },
{ id: 124, value: "value2", name: "Name1" },
{ id: 125, value: "value3", name: "Name2" },
{ id: 126, value: "value4", name: "Name2" }
];
// 利用 Set 进行转化
const names = [...new Set(array.map(a => a.name))];
// 利用数组记录
const names = array.reduce(function(a, b) {
if (a.indexOf(b.name) == -1) {
a.push(b.name);
}
return a;
}, []);
console.log(names);
Set | 集合
集合也是一种常见的数据结构,在 ES6 中添加了对于集合的支持,其基本用法如下:
// Sets
const s = new Set();
s.add("hello")
.add("goodbye")
.add("hello");
s.size === 2;
s.has("hello") === true;
WeakSet
WeakSet 提供了一种自回收的存储方式:
// Weak Sets
const ws = new WeakSet();
ws.add({ data: 42 });
// Because the added object has no other references, it will not be held in the set