专题:数组方法
创建
数组创建的方法
es5的Array方法可以创建数组,但是参数只有一个时创建会存在歧义
console.log(Array()); //[]console.log(Array(2)); //[empty × 2]console.log(Array(1, 2, 3)); //[1, 2, 3]
es6的Array.of静态方法解决以上歧义
console.log(Array.of()); //[]console.log(Array.of(2)); //[2]console.log(Array.of(1, 2, 3)); //[1, 2, 3]
长度
关于数组和字符串的长度:
操作数组的长度是可变的,而字符串长度是不变的
示例:
//字符串push新增var str = 'hello';str.push('vue');console.log(str);//报错 str is not a function//强行调用字符串的push方法Array.prototype.push.call(str, 'vue');console.log(str);//报错 Cannot assign to read only property 'length' of object '[object String]'//如何实现字符串长度增加?利用字符串拼接str += 'vue';
转字符串
将数组转为字符串的方法有toString
var arr = ['a', 'b', 'c'];var res = arr.toString();console.log(res);//a,b,c
toString方法也可以实现数组多维降维的操作:
var arr = ['a', 'b', ['c', ['d', 'e']]];var res = arr.toString();console.log(res);//a,b,c,d,e
扁平化
除了用toString方法,join方法也同样可以实现数组扁平化操作,但是如果以某一个字符串的形式拼接时只会扁平化一层
var arr = ['a', 'b', ['c', ['d', 'e']]];//以默认的形式拼接时var res = arr.join();console.log(res);//a,b,c,d,e//当以'-'的形式拼接时,只能扁平化一层var res1 = arr.join('-');console.log(res1);
最原始化的扁平化方式
//要求:编写一个程序将数组扁平化并将扁平化后的数组去重,最终得到一个升序且不重复的一维数组var arr = [[1, 2, 2],[3, 4, 5, 5],[6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];//分析//1.扁平化 多维数组 -> 一维数组//2.数组元素去重//3.数组元素升序//1.扁平化程序console.log(faltten(arr));//[1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]function faltten(arr) {//有传数组用有传数组,没有时用空数组var _arr = arr || [],// 新数组容器fArr = [],//保存并简写数组长度len = _arr.length,item;for (var i = 0; i < len; i++) {//数组元素item = _arr[i];//1.检测一维数组的数组元素是否为数组function _isArr(item) {//证明为数组元素是数组return {}.toString.call(item) === '[object Array]';}//2.如果是数组,需要用到递归再次扁平化数组if (_isArr(item)) {//把扁平化的单一数组拼接为一个整合数组fArr = fArr.concat(faltten(item));} else {//如果单一项不是数组,把该项push进数组fArr.push(item);}}return fArr;}
原始方法的健全写法
//原始方法的健全写法Array.prototype.faltten = function () {//好习惯:保存this,谁调用执行谁var _arr = this,toStr = {}.toString,fArr = [];if (toStr.call(_arr) !== '[object Array]') {throw new Error('只有数组才能调用flatten方法');}// 写法一:forEach_arr.forEach(function (item) {toStr.call(item) === '[object Array]' ?fArr = fArr.concat(item.faltten()) :fArr.push(item);});return fArr;//写法二:reduce 归纳return _arr.reduce(function (prev, item) {return prev.concat(toStr.call(item) === '[object Array]' ?item.faltten() :item);}, []);}//faltten方法调用console.log(arr.faltten());//[1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]
es6原始写法
//es6简写:const flatten = arr => arr.reduce((prev, item) =>prev.concat({}.toString.call(item) === '[object Array]' ? flatten(item) : item), []);//标准写法const flatten = (arr) => {return arr.reduce((prev, item) => {return prev.concat({}.toString.call(item) === '[object Array]' ? flatten(item) : item)}, [])}//flatten方法调用console.log(flatten(arr));//[1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]
去重
//写法一:// 最先想到的办法: for循环function uniqueArr(array) {//数组容器var _arr = [],isReapeat;for (var i = 0; i < array.length; i++) {//默认为falseisReapeat = false;//遍历数组容器for (var j = 0; j < _arr.length; j++) {//证明重复了if (_arr[j] == array[i]) {//并定义为trueisReapeat = true;//不能往_arr容器里增加元素break;}}//这里外层for循环仍会继续循环//如需终止循环,声明变量isReapeat枷锁if (!isReapeat) {//在循环外push元素_arr.push(array[i]);}}return _arr;}console.log(uniqueArr(arr).sort());;[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//写法二: 当前项对比下一项,如不重复push进去//效率较慢function uniqueArr(array) {var _arr = [],isReapeat;for (var i = 0; i < array.length; i++) {isReapeat = false;for (var j = i + 1; j < array.length; j++) {if (array[i] == array[j]) {isReapeat = true;break;}}if (!isReapeat) {_arr.push(array[i]);}}return _arr;}console.log(uniqueArr(arr).sort());;//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//写法三//filterfunction uniqueArr(array) {return array.filter(function (item, index) {//相等代表不重复//filter返回新数组//indexOf(item)只返回一次元素下标,无论元素重复多少个return array.indexOf(item) === index;// return array.indexOf(item);//[2, 6, 3, 5, 0, 3, 6, 8, 9, 4, 4, 2, 0, 9, 5, 2, 7, 4, 2, 3, 4, 6]// return index;//[1, 2, 6, 3, 5, 0, 3, 6, 8, 9, 4, 4, 2, 0, 9, 5, 2, 7, 4, 2, 3, 4, 6]//return array.indexOf(item) === index;//[1, 2, 6, 3, 5, 0, 8, 9, 4, 7]})}console.log(uniqueArr(arr).sort());
//写法四//利用forEachfunction uniqueArr(array) {var _arr = [];array.forEach(function (item) {if (_arr.indexOf(item) === -1) {_arr.push(item);}})return _arr;}console.log(uniqueArr(arr));//[1, 2, 6, 3, 5, 0, 8, 9, 4, 7]
//写法五//利用sortfunction uniqueArr(array) {var _arr = [];//先排序后循环//此操作会把相同的项排序在一起array.sort();// console.log(array);//[0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 9]for (var i = 0; i < array.length; i++){// 利用sort写法一//如当前项跟下一项不相等if (array[i] !== array[i + 1]) {_arr.push(array[i]);}// 利用sort写法二//原理:找最后一项对比if (array[i] !== _arr[_arr.length - 1]) {_arr.push(array[i]);}}return _arr;}console.log(uniqueArr(arr));//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//写法六//es6 - include()function uniqueArr(array) {var _arr = [];array.forEach(function (item) {if (!_arr.includes(item)) {_arr.push(item);}});return _arr;}console.log(uniqueArr(arr).sort());//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
indexOf()和include()区别:
indexOf: 返回-1/index可返回具体位置,对NaN无效include:返回true/false不可返回具体位置,对NaN有效
//写法七//reduce sortfunction uniqueArr(array) {var _arr = [],//Set数据结构里面的值是唯一的_temp = new Map();for (var i = 0; i < array.length; i++) {//如果拿不到数组该元素if (!_temp.get(array[i])) {//map里面没有该属性,应往里添加属性//myMap.set(元素的键, 元素的值);返回值 Map 对象// console.log(array[i]);//{array[i] => 1}_temp.set(array[i], 1);//把键名push到数组里// console.log(array[i]);_arr.push(array[i]);}}return _arr;}console.log(uniqueArr(arr).sort());//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//写法八//Array.from()function uniqueArr(array) {//将类数组(对象)转为数组return Array.from(new Set(array));}console.log(uniqueArr(arr).sort());
转类数组
es6中的Array.from静态方法可以将类数组转为数组,和es5中的Array.prototype.slice.call()方法实现一致
function test(a, b) {console.log(Array.from(arguments));//[1, 2]}test(1, 2);var str = 'hello';console.log(Array.from(str));//['h', 'e', 'l', 'l', 'o']
元素增删查
堆栈
push,unshift方法的返回值均为数组的长度
var arr = ['a', 'b', 'c'];var res1 = arr.push('d');console.log(arr, res1);//['a', 'b', 'c', 'd'] 4var res2 = arr.unshift('0');console.log(arr, res2);//['0', 'a', 'b', 'c', 'd'] 5
pop,unshift方法的返回值是删除的该项元素
var res3 = arr.pop();console.log(arr, res3);//['0', 'a', 'b', 'c'] 'd'var res4 = arr.shift();console.log(arr, res4);//['a', 'b', 'c'] '0'
截取
splice方法可以对数组元素进行截取,会操作原数组
var arr1 = ['a', 'b', 'c'];var arr2 = ['a', 'b', 'c', 'd'];var arr3 = ['a', 'b', 'c', 'd'];var arr4 = ['a', 'b', 'c', 'd'];var arr5 = ['a', 'b', 'c', 'd'];var arr6 = ['a', 'b', 'c', 'd'];//只有一个参数时,返回删除元素组成的数组,没有时为空数组var res1 = arr1.splice();console.log(arr1, res1);//['a', 'b', 'c'] []var res2 = arr2.splice(2);console.log(arr2, res2);//['a', 'b'] ['c', 'd']//两个参数时,返回删除元素组成的数组//参数1:起始增加或删除的位置//参数2:截取长度var res3 = arr3.splice(0, 2);console.log(arr3, res3);//['c', 'd'] ['a', 'b']var res4 = arr4.splice(0, 3);console.log(arr4, res4);//['d'] ['a', 'b', 'c']//三个参数时,返回删除元素组成的数组,修改指定位置为指定元素var res5 = arr5.splice(0, 1, 'hello');console.log(arr5, res5);//['hello', 'b', 'c', 'd'] ['a']//第二参数为undefined/-1/NaN/null,不会发生截取内容时,返回空数组var res6 = arr6.splice(0, null);console.log(arr6, res6);//['a', 'b', 'c', 'd'] []
slice方法可以对数组元素进行截取,返回新的数组
var arr = ['a', 'b', 'c'];//slice返回截取内容,第一位到最后//[) 左闭右开 左包含右不包含var res1 = arr.slice(1);console.log(arr, res1);//['a', 'b', 'c'] ['b', 'c']var res2 = arr.slice(1, 2);console.log(arr, res2);//['a', 'b', 'c'] ['b']
slice方法也可以将字符串转为数组
var str = 'hello';var arr = Array.prototype.slice.call(str);console.log(str, arr);//hello ['h', 'e', 'l', 'l', 'o']
slice方法也可以将类数组转为数组
function test(a, b) {console.log(arguments);//Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]var arr = Array.prototype.slice.call(arguments);console.log(arr);//[1, 2]}test(1, 2);
排序
正序
//sort方法操作的是原数组var arr = [1, 2, 3];var res = arr.sort((a, b) => a - b);console.log(arr, res);//[1, 2, 3] [1, 2, 3]
倒序
var arr = [1, 2, 3];var arr2 = [4, 5, 6];//reverse方法操作的是原数组var res1 = arr.reverse();console.log(arr, res1);//[3, 2, 1] [3, 2, 1]//sortvar res2 = arr2.sort((a, b) => b - a);console.log(arr2, res2);//[6, 5, 4] [6, 5, 4]
乱序
var arr = [1, 2, 3];var res = arr.sort(() => {var ran = Math.random();// console.log(ran);//0.1 - 0.9return ran - 0.5;});console.log(arr, res);//[1, 3, 2] [1, 3, 2]
拼接
concat方法操作返回的是新的数组,并且只能拼接多维数组中的第一层,多层降维时需要递归拼接
var arr = [1, 2, 3];var res1 = arr.concat(4);console.log(arr, res1);//[1, 2, 3] [1, 2, 3, 4]var res2 = arr.concat(4, [5, 6]);console.log(arr, res2);//[1, 2, 3] [1, 2, 3, 4, 5, 6]var res3 = arr.concat(4, [5, [6, 7]]);console.log(arr, res3);//[1, 2, 3] [1, 2, 3, 4, 5, Array(2)]
es6拓展运算符的方法进行拼接,不能降维操作
var arr = [1, 2, 3];var res1 = [...arr, 4];console.log(arr, res1);//[1, 2, 3] [1, 2, 3, 4]var res2 = [...arr, 4, [5, 6]];console.log(arr, res2);//[1, 2, 3] [1, 2, 3, 4, Array(2)]var res3 = [...arr, 4, [5, [6, 7]]];console.log(arr, res3);//[1, 2, 3] [1, 2, 3, 4, Array(2)]
索引
indexOf和lastIndexOf是查找索引的方法,区别在从前面或后面顺序开始查找
//返回查找元素的索引var arr = ['a', 'b', 'c'];console.log(arr.indexOf('a')); //0console.log(arr.indexOf('c')); //2console.log(arr.lastIndexOf('a')); //0console.log(arr.lastIndexOf('c')); //2
包含
includes方法查找数组是否包含指定元素,返回布尔值
var arr = ['a', 'b', 'c'];console.log(arr.includes('a')); //trueconsole.log(arr.includes('d')); //false
查找
es6的find方法返回第一个符合条件的数组元素,参数是一个定义条件的函数
var arr = [1, 2, 3, 4, 5];console.log(arr.find((n) => n > 2)); //3
es6的findIndex方法返回第一个符合条件的数组元素的索引,参数是一个定义条件的函数
var arr = [1, 2, 3, 4, 5];console.log(arr.findIndex((n) => n > 2)); //2
填充
fill方法将数组内所有的元素填充为指定的值
var arr1 = ['a', 'b', 'c'];var arr2 = ['a', 'b', 'c'];var res1 = arr1.fill('d');console.log(arr1, res1);//['d', 'd', 'd'] ['d', 'd', 'd']//参数1为填充的值, 参数2和3是选定的区间 左闭右开var res2 = arr2.fill('d', 0, 1);console.log(arr2, res2);//['d', 'b', 'c'] ['d', 'b', 'c']
元素遍历
关于遍历键名/键值/键值对:
keys,values,entries方法返回的是一个有序数组可迭代对象,需要for..of遍历获取键名或键值或键值对
var arr = ['a', 'b', 'c'];for (var key of arr.keys()) {console.log(key); //0 1 2}for (var value of arr.values()) {console.log(value); //a b c}for (var [key, value] of arr.entries()) {console.log(key, value); //0 'a' 1 'b' 2 'c'}
forEach
forEach循环每一项数组元素,返回值为undefined,函数内部this指向window,第二参数可以改变this指向(回调函数箭头写法失效)
var arr = ['a', 'b', 'c'];console.log(arr.forEach(function(item){ console.log(this); //window })); //undefined
forEach和for循环的区别:
forEach遇到数组长度为0时forEach的内部函数并不会执行遍历forEach遇到稀疏数组时,空缺的元素并不会执行遍历forEach不可以break和continue中止或跳出循环forEach不可以遍历对象,可以[].forEach.call()遍历for遇到数组长度为0时不会执行循环for遇到稀疏数组时,会循环,缺失的元素会打印undefinedfor可以break和continue中止或跳出循环
map
根据原数组能够返回一个和原数组产生映射关系的数组
console.log([1, 2, 3].map((item) => item * 2));//[2, 4, 6]
filter
返回过滤后的数组元素组合的数组,函数内部必须返回布尔值,布尔值决定了当前过滤的方式,true留下,false过滤
console.log([1, 2, 3, 4].filter((item) => (item > 2 ? true : false)));//[3, 4]
some
返回布尔值,如果某一项数组元素符合条件返回true
console.log([1, 2, 3].some((item) => item === 2));//true
every
返回布尔值,如果所有项数组元素符合条件返回true
console.log([1, 2, 3].every((item) => item > 0));//trueconsole.log([1, 2, 3].every((item) => item > 1));//false
reduce
归纳函数,迭代器,累加器,当考虑想获取具体格式的值或数据格式时,可以考虑使用reduce
