diff --git a/js/数组api.js b/js/数组api.js new file mode 100644 index 0000000..d49e9b4 --- /dev/null +++ b/js/数组api.js @@ -0,0 +1,210 @@ +/* + 复习数组常用api + 问题? + 1.类型化数组 +*/ + +// 创建一个数组 +let arr = new Array(1, 2, 3, 4, 5, 6) // 使用构造函数创建 +let arr2 = [1,2,3,4,5,6,76,7] // 使用字面量 + +// 静态方法 +// Array.form() Array.from() 静态方法从可迭代或类数组对象创建一个新的浅拷贝的数组实例。 +let arrByFrom = Array.from({length: 10}, ()=>1) // 使用类数组来创建一个数组 +let setList = new Set(); // set是一个可迭代对象,实现了iterator接口 +setList.add(1); +setList.add(2); +setList.add(3); +let arrByFrom2 = Array.from(setList) // 将一个迭代对象转换为一个数组 +let arrByFrom3 = Array.from(setList, (item, index)=> { + // 第二个参数接收一个函数,将返回值作为初始值,回调函数的第一个参数为当前值,第二个参数为当前值在创建数组中的下标 + return item * index +}) + +// Array.isArray() +// console.log(Array.isArray(arr)) // 判断一个数据是非是数组 + +// console.log( Array.of(1,2,3) ) // 通过参数创建数组返回 【1,2,3】 + +// 实例方法 Array.prototype.at(), 接受一个整数下标返回下标内容 + +// console.log(arr.at(-1)) // 可接受正数和负数arr.at(1) = 2 arr.at(-1) = 6 +// console.log(arr.concat(arr2)) // 返回合并之后的新数组, 可实现数组的浅拷贝 + +// Array.prototype.entries() 可以返回数组的迭代对象[index, item] + +// for (let [index, item] of arr.entries()) { +// console.log(index + "---" + item) +// } + +// Array.prototype.every(fn) fn 返回一个布尔值,如果全部符合条件则every返回true +// 判断数组的所有内容是否大于0 +// console.log(arr.every((v)=>v>0)); +// 对类数组同样生效 +// let arrInObject = {length: 3, 0: 1, 1: 2, 2: 3} +// console.log(Array.prototype.every.call(arrInObject, (item)=>typeof item === "number")); + +// Array.prototype.fill(value, start, end) 使用一个静态的值填充数组,可以指定开始和结束位置,没有指定则填充全部 +// console.log(Array(10).fill(2,0,10)) +// 也可以填充类数组,会读取类数组的length +// console.log(Array.prototype.fill.call({length: 10}, 2)); + +// Array.prototype.filter(fn(item, index, arr)) 返回匹配条件的数组,如果没有则返回"[]" + +// console.log(arr.filter((value)=> value> 3)); +//console.log([1,,,,3].filter((value)=> value === undefined)); // 遇到空槽时是不会处理的 + +// Array.prototype.find(fn) 根据fn的判断返回元素, 若没有找到则返回undefined +// console.log([{id: 1, name: '小明'}, {id: 2, name: '小王'}].find((v)=>v.id===1)); +// Array。prototype.findLast(fn) 会返回最后一个下标 + +// Array.prototype.findIndex(fn) 根据条件,找到第一个符合要求的第一个下标 +// console.log(arr.findIndex((v)=> v>2)); +// Array.prototype.findLastIndex(fn) 根据条件,找到第一个符合要求的最后一个下标 +// console.log(arr.findLastIndex((v)=> v>2)); +// Array.prototype.indexOf(value) 根据给定的具体值,返回此值在数组中的小标,和findIndex的区别是不需要使用测试函数 +// console.log(arr.indexOf(2)); +// Array.prototype.includes(value, 开始搜索的位置) 返回一个布尔值,如果value存在在这个数组中,那么返回true +// console.log(arr.includes(1, -1)); // 显然在-1开始的位置没有一个数是1,所以返回false + + +// Array.prototype.some(fn) 这个和every相反,只要有一个符合条件就返回true +// console.log(arr.some((value)=>value>1)); + +// Array.prototype.flat(int) 可以展平一个数组,参数为要展开至多少层 +// console.log([1,[2,[3,[4,[5]]]]].flat(2)); // [ 1, 2, 3, [ 4, [ 5 ] ] ] +// 当传入Infinity时会全部展开 +// console.log([1,[2,[3,[4,[5]]]]].flat(Infinity)); // [ 1, 2, 3, 4, 5 ] + +// Array.prototype.forEach 会遍历数组中的每一个元素,如果想对原数组进行操作可以使用这个方法 +// arr.forEach((value, index, arr)=>{ +// console.log(`arr[${index}] = ${value}`) +// }) + + +// 使用forEach对数组进行扁平化 +// let flaten = (arr)=>{ +// const flatArr = [] +// arr.forEach(item=>{ +// if(Array.isArray(item)) { +// flatArr.push(...flaten(item)) +// }else{ +// flatArr.push(item) +// } +// }) +// return flatArr +// } + +// console.log(flaten([1,[2,[3,[4,[5]]]]])); + +// Array.prototype.join(). 可以将一个数组用指定的字符链接起来,默认是逗号 + +// console.log([1,2,3,4,5].join("hh")); + +// Array.prototype.keys() 会返回数组所有的index,缺失数组的也会返回 +// console.log([...[4,5,,6].keys()]); +// console.log(Object.keys([4,5,,6])); // 缺失项的下标是不会返回的 + +// Array.prototype.map() 当需要对数组进行格式化,又不需要对原数组操作时可以使用这个方法 +// console.log([[1,'小明'], [2, '小红'], [3, '小王']].map((item)=>({ id: item[0], name: item[1]}))); + +// pop,push,shift,unshift 可以添加或者修改元素,可以实现队列和栈的数据结构 +// console.log(arr.push(1)); // 在末尾添加一个元素,并且添加后数组的长度 +// console.log(arr.pop()); // 删除末尾的元素并且返回它 +// console.log(arr.shift()); // 删除数组的第一个元素,并且返回它 +// console.log(arr.unshift(8)); // 插入一个元素到数组的第一个位置,并且返回新数组的长度 + +// Array.prototype.reduce(fn) // 对数组中的每一个元素进行fn操作,并将返回值作为下一次函数的参数,最终返回这个值 + +// 使用reduce对数组内容求和 +// console.log([1,2,3,4,5].reduce((acc,cur)=> acc + cur)); // 当没有给初始值时使用数组第一个值作为acc,cur从第二个值开始,之后的acc为之前函数返回的值 + +// 思考这样一个问题我有一个对象数组,对象数组中的每一个对象元素都有一个money的属性,想在我想对这样一个属性求将如何操作,在不给初始值的情况下显然是不可以操作的,因为在没有给初始值的情况下第一次的acc为数组中的第一个元素,显然不能作求和操作,这个时候就需要设置一个初始值 +// console.log([{id: 1, money:399}, {id: 2, money: 699}, {id: 3, money: 800}].reduce((acc, cur)=> acc + cur.money, 0)); + +// reduce是非常强大的,可以做非常多的操作,再来想一想,这样一个操作,我想对下面这样一个对象数组进行条件格式化,当数组中id大于2的元素做一次格式化操作 + +let testArr = [{id: 1, age: 17}, {id: 2, age: 19},{id: 3, age: 20},{id: 4, age: 17}] +// 可以使用filter先过滤,再使用map + +// console.log(testArr.filter(item=>item.id > 2).map(item=> { +// if(item.age > 18) { +// return {...item, isAdult: true} +// }else { +// return {...item, isAdult: false} +// } +// })); +// 这样写有一个坏处,就是有两遍循环,数据量一大,就还慢,下面使用reduce一次性完成 + +// console.log(testArr.reduce((acc, cur)=> { +// if(cur.id <= 2) return acc +// if (cur.age > 18) { +// return [...acc, {...cur, isAdult: true}] +// } + +// return [...acc, {...cur, isAdult: false}] +// }, [])); + +// reduce 还可以使二维数组展平 +// console.log([[2],[2],[4],[5]].reduce((acc, cur)=>{ +// return acc.concat(cur) +// }, [])); + +// reduce对数组对象进行分组, 比如上面的testArr,我们将将年龄来进行分组,17岁的一组,20岁的一组 + +// 普通实现 +// let groupByAge = {} +// testArr.forEach(item => { +// if(groupByAge[item.age]) { +// groupByAge[item.age].push(item) +// }else { +// groupByAge[item.age] = [item] +// } +// }) +// console.log(groupByAge); + +// 使用reduce,可以不借助外部变量 +// console.log(testArr.reduce((acc, cur)=> { +// acc[cur.age] ? acc[cur.age].push(cur) : acc[cur.age] = [cur] +// return acc +// }, {})); +// reduceRight 和reduce类似,只不过是从右边开始遍历 + +// Array.prototype.reverse() 会翻转数组, 并且会对原数组直接操作 +// console.log([1,2,3,4,5].reverse()); + + +// Array.prototype.slice(start, end) 切截取数组的一部分返回,会做浅拷贝 +// console.log([1,2,3,4].slice(2,4)); +// console.log([1,2,3,4,5,6].slice(-2)) // 截取最后的两个元素 +// 在es6之前,可以使用slice实现类数组转换为数组 +// console.log(Array.prototype.slice.call({length:3, 0: 1, 1: 2, 2: 3})); + +// Array.prototype.sort() 可以对数组内容排序,默认是根据UTF16字符编码排序的 +// console.log([1,111,2,222,3].sort()); +// sort接收一个比较器,会传递两个参数a,b,当返回的值小于0时a会排在b的前面,当返回的值大于0时a会排在b的后面 +// console.log([1,111,2,222,3].sort((a,b)=>{ +// if(aa-b)) +// 反之可以写成(a,b)=> b-a 来实现倒序排序 +// console.log([1,111,2,222,3].sort((a,b)=>b-a)) +// 在es2019也就是es10之前,这个排序可能是不稳定的,因为规范没有要求是否要稳定排序,各家的实现也不一样,所以可能稳定,也可能不稳定 + +// Array.prototype.Splice(start, 删除的个数, 内容) +// let spliceArr = [1,2,3,4] +// spliceArr.splice(1,1) // 从第二个元素开始,删除一个 [ 1, 3, 4 ] +// spliceArr.splice(1) // 删除第二个元素之后的所有元素 +// spliceArr.splice(1,0,4,5,6) // 从第二个位置插入数据 +// spliceArr.splice(1,1,4,5,6) // 从第二个位置插入数据并且覆盖原本的第二个数 +// spliceArr.splice(-1) // 删除倒数第一个数 +// spliceArr.splice(spliceArr.length, 0,5) // 在原数组的后面添加一个数值,可实现push功能 +// spliceArr.splice(0,0,0) // 在数组的最前面添加一个数值,可实现unShift() +// console.log(spliceArr); + +// Array.prototype.values() 返回数组值的迭代对象