1、会修改原数组的方法
-
1.1 push: 向数组末尾添加一个或多个元素,数组长度增加相应长度,返回数组长度
-
1.2 pop: 删除数组末尾元素,数组长度减一,返回被删除的元素
-
1.3 unshift: 向数组首部添加一个或多个元素,数组长度增加相应长度,返回数组长度
-
1.4 shift: 删除数组首部元素,数组长度减一,返回被删除的元素
-
1.5 reverse: 翻转数组
手写实现:// 遍历数组前一半元素,让其与数组对应的后一半元素交换 Array.prototype.myReverse = function(){ const len = this.length const mid = Math.floor(len/2) for(let i=0; i<mid; i++) { let tmp = this[i] this[i] = this[len-i-1] this[len-i-1] = tmp } return this } -
1.6 splice: 用于增删改原数组,splice(index, count, ...items[]) 第一个参数是数组的目标下标位置index,第二个参数是从目标位置开始(包括目标位置)往后count个元素,第三个参数是将这count个元素替换为传入的...items[]
手写实现:Array.prototype.mySplice = function(index, count, ...args) { /* 删除count个元素,添加args.length个元素,所以,我们需要将index+count位置后面的所有元素 向左或者向右移动|args.length-count|个位置,给删除以及添加腾位置 */ let argLen = args.length let arrLen = this.length const retArr = [] // 如果count为undefined,则需要删除index以及之后的所有元素,需要将count置为数组长度减index if(!count) count = arrLen - index // 需要移动的步数 let moveStep = args.length - count // 首先将要被删除的元素存到一个数组里,之后需要返回删除的数组 for(let i=index; i<count+index; i++) { retArr.push(this[i]) } // 若添加的元素比删除的元素多,则将index+count位置之后的元素向右移动moveStep步 if(moveStep >= 0) { for(let i=arrLen-1; i>=index+count; i--) { this[i+moveStep] = this[i] } } else { moveStep = Math.abs(moveStep) // 否则向左移动 for(let i=index+count; i<arrLen; i++) { this[i-moveStep] = this[i] } this.length -= moveStep } // 再将index以及之后args.length个元素放到index以及index之后 for(let i=index; i<argLen+index; i++) { this[i] = args[i-index] } return retArr } -
1.7 sort: 传入一个回调函数,用于给数组排序,回调函数接收两个参数,a,b,sort会遍历一遍数组,依次将相邻的两个元素传给回调函数的a,b,若回调函数返回值大于0,则b会在a的前面,小于0,a会在b的前面,等于0,ab的相对位置不变
手写实现:(以简单的冒泡排序实现,实际的sort实现要更复杂,更高效)// 大概是这样,简单实现 Array.prototype.mySort = function(cbFn) { const len = this.length for(let i=0; i<len-1; i++) { for(let j=0; j<len-i-1; j++) { if(cbFn(this[j],this[j+1]) > 0) { let tmp = this[j] this[j] = this[j+1] this[j+1] = tmp } } } return arr }
2、不修改原数组的方法
-
2.1 map map方法接收一个回调函数,回调函数接收一个参数,map方法会遍历数组,将每个元素作为参数传入回调函数,每次调用回调函数,会将返回值替换为当前遍历到的数组元素的值
手写实现:// 大概是这样 Array.prototype.myMap = function(cbFn) { const retArr = []; const len = this.length for(let i=0; i<len; i++) { retArr.push(cbFn(this[i])) } return retArr } -
2.2 reduce 此方法接收两个参数,第二个参数可选,第一个参数是一个回调函数,回调函数接收两个参数,第一次调用时,若reduce有接收第二个参数,则回调函数的第一个参数为reduce接收的第一个参数,第二个参数为数组的第一项;若reduce没有接收第二个参数,则回调函数的第一个参数为数组的第一项,第二个参数为数组的第二项,之后每次调用,数组元素向后遍历,回调函数的第一个参数为上一次回调函数调用的返回值,第二个参数为当前遍历到的数组元素,实现不断地累计,获取到累计值
手写实现:// 大概这样实现 Array.prototype.myReduce = function(cbFn, start) { const len = this.length let acc = start ? start : this[0] let startIdx = start ? 0 : 1 // 若数组元素小于2且没有start if((len === 1 && !start) || len === 0) { return } for(let i=startIdx; i<len; i++) { acc = cbFn(acc, this[i]) } return acc } -
2.3 concat 接收一个数组,将此数组与接收的数组连起来,返回一个新数组
手写实现:Array.prototype.myConcat = function(otherArr) { return [...this, ...otherArr] } -
2.4 filter 传入一个回调函数,回调函数里接收的参数是原数组的每一项,回调函数需要返回一个布尔值,若为true将数组里的这一项加入新数组
手写实现:Array.prototype.myFilter = function(cbFn) { let len = this.length const retArr = [] for(let i=0; i<len; i++) { let tmpBool = cbFn(this[i]); if(tmpBool) retArr.push(this[i]) } return retArr } -
2.5 flat 传入一个number,不传默认为1,指定深度,打平数组
手写实现// 递归地调用flat,将数组打平到depth深度 Array.prototype.myFlat = function(depth=1) { if(depth === 0) { return this } const ret = [] let len = this.length for(let i=0; i<len; i++) { if(Array.isArray(this[i])) { ret.push(...(this[i].myFlat(depth-1))) } else { ret.push(this[i]) } } return ret }
大致写这么多吧,数组方法还有挺多的,如some,every,includes,indexOf,用起来也都挺简单的,实现也都挺简单的,找准方法接收什么参数,接收回调的话,回调需要接收什么参数,它实现什么效果,知道了这些,按照它需要实现的效果来就行了,当然我的实现也都是最简单的方式,不是完善的方式,还有很多边界条件没考虑,数组的使用还是挺简单的。