声明
1 2 3 4
| var a=new Array(); var a=new Array(5); var a=new Array([5]); var a=[5];
|
判断是否为数组
拼接为字符串
数组的增删改
添加
1 2 3 4
| a.push("123");
a.unshift("456");
|
插入另一个数组
1 2 3
| let array1 = [1, 2, 3]; let array2 = [4, 5, 6]; array1 = [...array1, ...array2];
|
插入
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目的数组。
**注释:**该方法会改变原始数组。
插入 在index位置插入元素
1
| arr.splice(index,0,item1,item2,...);
|
开始插入
结尾插入
替换元素
**注释:**该方法会改变原始数组。
替换 从index开始的2个元素替换为
1
| a.splice(index,2,item1,item2,...);
|
删除元素
删除索引位置元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| let myArray = [1, 2, 3, 4, 5];
let deletedElements = myArray.splice(2, 1); console.log(deletedElements); console.log(myArray);
deletedElements = myArray.splice(1, 2); console.log(deletedElements); console.log(myArray);
deletedElements = myArray.splice(0, 0); console.log(deletedElements); console.log(myArray);
|
删除最后一个
**注释:**该方法会改变原始数组。
pop() 方法将删除 arrayObject 的最后一个元素,
把数组长度减 1,并且返回它删除的元素的值。
如果数组已经为空,则 pop() 不改变数组,并返回 undefined 值。
从索引删除
删除 从index开始删除2个元素
删除第1个元素
删除最后2个元素
要删除数组的最后两个元素,可以使用数组的 slice() 方法或 splice() 方法。
使用 slice() 方法:
1 2 3 4
| let array = [1, 2, 3, 4, 5];
let newArray = array.slice(0, array.length - 2); console.log(newArray);
|
使用 splice() 方法:
1 2 3 4
| let array = [1, 2, 3, 4, 5];
array.splice(array.length - 2, 2); console.log(array);
|
保留前3个元素
1 2 3 4
| let array = [1, 2, 3, 4, 5];
array.splice(3, array.length - 3); console.log(array);
|
移除对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let arr = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' } ];
let objToRemove = { id: 2, name: 'Bob' };
let index = arr.findIndex(obj => obj.id === objToRemove.id); if (index !== -1) { arr.splice(index, 1); }
console.log(arr);
|
遍历中删除数据
一般解决:此时可以在删除下标i的时候执行 i–(使下标回退一个位置)
优化解决:可以通过倒叙遍历的方法,倒叙遍历的时候不管删了多少元素,没遍历的元素不会被跳过,比上一个方法简单
一般解决方法
1 2 3 4 5 6 7
| let arr = [1,2,3]; for(let i=0; i<arr.length; i++){ if(arr[i]==2){ arr.splice(i, 1); i--; } }
|
优化方法
1 2 3 4 5
| for(let i=arr.length-1; i>=0; i--){ if(arr[i] == 2){ arr.splice(i,1); } }
|
清空数组
方式1:splice函数
1
| arrayObject.splice(index,howmany,element1,.....,elementX)
|
示例:
1 2
| var arr = [1,2,3,4]; arr.splice(0,arr.length);
|
方式2:直接赋予新数组 []
1 2
| var arr = [1,2,3,4]; arr = [];
|
这种方式为将arr重新复制为空数组,之前的数组如果没有被引用,将等待垃圾回收。
方式3:给数组的length赋值为0
1 2
| var arr = [1,2,3,4]; arr.length = 0;
|
赋予数组的长度小于本身的长度,数组中后面的元素将被截断。
赋予数组的长度大于本身的长度,将扩展数组长度,多的元素为undefined。
注意
VUE的时候不要用这种方式,会导致页面不刷新。
效率比较:
多次测试发现第3种方式最快,第1种其次,第2种最慢。
排序
会修改原数组
数组反转
该方法会改变原来的数组,而不会创建新的数组。
单属性排序
正序:
正序:
1 2
| var arr = [40, 100, 1, 5, 25, 10]; arr.sort(function(a, b){return a - b});
|
逆序:
1 2
| var arr = [40, 100, 1, 5, 25, 10]; arr.sort(function(a, b){return b - a});
|
多属性排序
根据多个属性排序
先按type正序,再按num倒序
1 2 3 4 5 6 7
| arr.sort(function(a,b){ if(b.type==a.type){ return b.num-a.num }else{ return a.type-b.type } })
|
字符串排序
1 2 3 4 5
| arr.sort( function(a,b){ return a.localeCompare(b) } )
|
如果包含中文
1
| a.localeCompare(b,'zh-CN')
|
随机排序
1
| array.sort(() => Math.random() - 0.5)
|
null排序
列表中的对象的属性为null的排后面。
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
| var array = [ { name: "Mike", sex: "男" }, { name: "John", sex: "女" }, { name: "Alice", sex: null }, { name: "Bob", sex: "男" }, { name: "Emma", sex: null } ];
array.sort(function(a, b) { let aValue = a.sex; let bValue = b.sex; if (aValue === null && bValue === null) { return 0; } else if (aValue === null) { return 1; } else if (bValue === null) { return -1; } else { return aValue.toString().localeCompare(bValue.toString(), "zh-CN"); } });
console.log(array);
|
深拷贝与浅拷贝
深拷贝
1 2 3
| const arr = [1, 2, 3, 4, 5]; const clone = JSON.parse(JSON.stringify(arr)); console.info(clone);
|
浅拷贝
方式1
使用展开运算符可以轻松地复制
1 2 3
| const arr = [1, 2, 3, 4, 5]; const clone = [...arr]; console.info(clone);
|
方式2
使用数组的slice方法复制数组
1 2 3
| const arr = [1, 2, 3, 4, 5]; const clone = arr.slice(); console.info(clone);
|
slice() 是数组对象的一个方法,用于从数组中提取指定位置的元素创建一个新的数组。
slice() 方法不会修改原始数组,而是返回一个浅拷贝(shallow copy)的新数组。
slice() 方法可以接收两个参数,即 start 和 end。起始位置 start 是要提取的起始索引(包含在提取范围内),结束位置 end 是要提取的结束索引(不包含在提取范围内)。
如果省略 end 参数,默认会提取到数组的末尾。
合并两个数组
concat() 方法用于连接两个或多个数组。
该方法不会改变原数组,而仅仅会返回被连接数组的一个副本。
获取数组片段
按照位置获取
不会改变原数组
1
| arrayObject.slice(start,end)
|
参数
返回值
- 返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
获取除最后一个的其他
1 2
| let arr = [1,2,3,4,5]; arr.slice(0,arr.length-1);
|
获取最后一个
1 2
| let arr = [1,2,3,4,5]; arr.slice(arr.length-1);
|
随机获取2个
1 2 3 4
| export function getRandomTwoItems(arr) { const shuffledArray = [...arr]; return shuffledArray.sort(() => 0.5 - Math.random()).slice(0, 2); }
|
判断是否包含
数组是否包含元素
1 2 3 4
| var arr = ["a","b","2","3","c"]; if(arr.indexOf("a")!==-1){
}
|
数组是否包含元素
1 2 3 4
| let animals = ["a", "b", "c", "d"]
animals.includes("a") animals.includes("f")
|
包含元素或属性
判断是否为数组的元素索引或对象的属性:
格式:(变量 in 对象)
当对象为数组时,变量指的是数组的索引;
当对象为对象是,变量指的是对象的属性。
数组示例:
1 2 3 4 5
| var arr = ["a","b","2","3","str"]; var result = ("b" in arr); var result1 = (4 in arr); console.info(result); console.info(result1);
|
输出为:
对象示例:
1 2 3 4 5 6 7 8 9 10 11
| var obj={ w:"wen", j:"jian", b:"bao" }
var result=(2 in obj); var result1=("j" in obj);
console.info(result); console.info(result1);
|
输出为:
判断数组包含另一数组
1 2 3 4
| function isArrayContained(arr1, arr2) { return arr2.every((item) => arr1.includes(item)); }
|
判断数组是否包含对象
1 2 3 4 5
| let animals = [{name: "dog"}, {name: "snake"}, {name: "monkey"}, {name: "donkey"}] let aname = "monkey";
var result = animals.some(animal => animal.name === aname); console.log(result);
|
遍历
1 2 3 4 5
| var arr = [1, 2, 3, 4, 5];
arr.forEach((item) => { console.log(item); });
|
map
map()经常用来遍历数据。
map()的作用就是“映射”,也就是原数组被“映射”成对应新数组。
方法概述
map() 方法返回一个新数组,这个新数组:由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
map() 不会对空数组进行检测。
map() 不会改变原始数组。
1 2 3 4 5 6
| var arr = ["a","b","c","d","e"]; arr.map(function(currentValue,index,arr){ console.log("当前元素"+currentValue) console.log("当前索引"+index) console.log("数组对象"+arr) })
|
map的参数:
- currentValue 必须。当前元素的值
- index 可选。当期元素的索引值
- arr 可选。当期元素属于的数组对象
reduce
求和
1
| let totalValue = list.reduce((total, item) => { return total + item }, 0)
|
最大值
1
| let maxValue = list.reduce((max, item) => { return Math.max(max, item) }, 0)
|
filter
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
注意: filter() 不会对空数组进行检测。
注意: filter() 不会改变原始数组。
1 2 3 4 5 6 7
| var ages = [32, 33, 12, 40];
function checkAdult(age) { return age >= 18; }
var a2 = ages.filter(checkAdult);
|
排除数组元素的数组
1 2 3 4
| const array = [1, 2, 3, 4, 5]; const exclude = [2,3]; const newArray = array.filter(item => exclude.indexOf(item)===-1); console.log(newArray);
|
some
1 2 3 4
| const array = [1, 2, 3, 4, 5];
const hasNumber = array.some(element => element===2); console.log(haNumber);
|
要判断一个二维数组中是否包含另一个一维数组,你可以使用嵌套的 Array.prototype.some() 和 Array.prototype.every() 方法来实现。
首先,你可以使用 some() 方法遍历二维数组的每个子数组,然后对每个子数组使用 every() 方法来判断是否包含目标数组。
下面是一个示例:
1 2 3 4 5 6 7 8
| const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; const targetArray = [4, 5, 6];
const includesTarget = matrix.some(subArray => subArray.length === targetArray.length && subArray.every((element, index) => element === targetArray[index]) );
console.log(includesTarget);
|
在上面的示例中,includesTarget 的值将根据二维数组 matrix 是否包含目标数组 targetArray 来决定。
subArray.every() 用于检查每个子数组是否与目标数组完全匹配(即元素个数和每个元素的值都相等)。
every
判断数组中不为空的都是整数
1 2 3 4 5 6 7
| let numArr = [10,8,null,10,20,100]; numArr = numArr.filter(item=>item!=null && item!=""); console.info(numArr); let result = numArr.every(item=>{ return new RegExp("^[0-9]+$", "i").test(item+""); }); console.info(result);
|
fill
1 2 3
| let arr = new Array(5); arr.fill(0); console.info(arr);
|
注意填充二位数组
1 2 3 4
| let dataArr = new Array(5); dataArr.fill(new Array(8).fill(0)); dataArr = JSON.parse(JSON.stringify(dataArr)); console.info(dataArr);
|
注意
这里使用JSON进行了序列化和反序列化的原因是dataArr中填充的数组是同一指针的数组,修改的化会全都改变。
还用一种方式
1
| let dataArr = Array.from({length: 3}, () => []);
|
队列的实现
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| function Queue() { this.items = [] Queue.prototype.enqueue = element => { this.items.push(element) }
Queue.prototype.dequeue = () => { return this.items.shift() }
Queue.prototype.front = () => { return this.items[0] }
Queue.prototype.isEmpty = () => { return this.items.length === 0; }
Queue.prototype.size = () => { return this.items.length }
Queue.prototype.toString = () => { let resultString = '------------队列------------\n' for (let i of this.items) { resultString += JSON.stringify(i) + '\n' } resultString += '------------队列------------\n' return resultString }
Queue.prototype.clear = () => { this.items = []; } }
|
使用
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 28 29 30 31 32 33 34 35 36 37 38 39 40
| window.msgQueue = new Queue();
function checkQueue() { let now = parseInt(new Date().getTime() / 1000 + ""); if (window.msgQueue.size() > 0) { let msg = window.msgQueue.front(); if (now - msg.timeunix > 3) { if (window.ws && window.ws.readyState === 1) { let timeunix = parseInt(new Date().getTime() / 1000 + ""); msg.timeunix = timeunix; msg.b.timeunix = timeunix; let str = JSON.stringify(msg); let msgEnc = encStr(str); window.ws.send(msgEnc) if (show_log) { console.info("↑ WS消息重发", msg); } } } } setTimeout(function () { checkQueue(); }, 300) }
checkQueue();
if (msgObj.c === 666) { if (window.msgQueue.size() > 0) { let msgitem = window.msgQueue.front(); if (msgitem.mid === msgObj.mid) { logger.info("队列移除消息", msgitem) window.msgQueue.dequeue(); } logger.info("队列剩余消息条数", window.msgQueue.size()) } }
|
这种情况会出现一个问题
如果在断网时发送消息,这个消息会在队列中,当重连时,会发送之前的消息,并且发送上线的消息,可能先收到的是上线消息的返回,但是上线消息不是在队列的顶部所以没有移除,就会出现问题。
解决方法
发消息依旧按照队列发送,但是接收消息的时候只要在数组中都移除。
示例
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| window.msgQueue = [];
function checkQueue() { let now = parseInt(new Date().getTime() / 1000 + ""); if (window.msgQueue.length > 0) { let msg = window.msgQueue[0]; if (now - msg.timeunix > 3) { if (navigator.onLine && window.ws && window.ws.readyState === 1) { let timeunix = parseInt(new Date().getTime() / 1000 + ""); msg.timeunix = timeunix; msg.b.timeunix = timeunix; let str = JSON.stringify(msg); let msgEnc = encStr(str); window.ws.send(msgEnc) if (show_log) { console.info("↑ WS消息重发", msg); } } } } let retryTime = 3000; if (window.msgQueue.length > 0) { retryTime = 1000; } setTimeout(function () { checkQueue(); }, retryTime); }
checkQueue();
if (msgObj.c === 666) { if (window.msgQueue.length > 0) { console.info("移除前-队列消息条数", window.msgQueue.length) for (let i = window.msgQueue.length - 1; i >= 0; i--) { let msgitem = window.msgQueue[i]; if (msgitem.mid === msgObj.mid) { if (show_log) { console.info("队列移除消息", i, msgitem) } window.msgQueue.splice(i, 1); } } if (show_log) { console.info("移除后-队列消息条数", window.msgQueue.length) } } }
|