本文原载于CSDN
此文章将会介绍数组大部分的原生方法的用法,并自己实现一个具有相同功能的方法,不定期更新。顺序暂时看起来比较乱,所有方法都写完后会重新整理一下。
概述 JS原生数组方法的参数都大致符合下面的通式(针对不同的参数,会在遇到之后补充),比较常见的方法一大部分都是遍历一遍数组,然后给每个元素执行一次提供的函数,也就是回调函数,所以实现基本都是基于遍历的。其他的,会在后面详细说明。
arr.method( function (value, index, arr ) { }, thisValue)
大致将数组方法分为两类,一类是改变原数组的方法,一类是不改变原数组的方法。
arr.push(); arr.pop(); arr.unshift(); arr.shift(); arr.reverse(); arr.solice(); arr.sort(); arr.copyWithin(); arr.concat(); arr.toString(); arr.slice(); arr.join(); arr.split(); arr.forEach(); arr.map(); arr.filter(); arr.some(); arr.every(); arr.concat();
forEach()
forEach()
方法用于调用数组的每个元素,并将元素传递给回调函数。
forEach()
没有什么好说的,就是遍历数组的所有元素,需要注意的就是此方法不会改变原数组。使用方法如下
var arr = [1 , 2 , 3 , 4 , 5 , 6 , 7 ]arr.forEach(function (val, index, arr ) { console .log(val) })
实现起来也很简单,就是遍历一次数组,然后给每个元素都执行一次回调函数,直接上实现代码
Array .prototype.myForEach = function (fn, callback ) { if (typeof fn === 'function' ) { for (var i = 0 , len = this .length; i < len; i ++) { fn.call(callback, this [i], i, this ) } } }
map()
map()
方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map()
就相当于是在 forEach()
方法上的扩展,遍历所有元素并以相同的规则改变元素后返回一个新数组。用法如下
var arr = [1 , 2 , 3 , 4 ]var newArr = arr.map(function (val, index, arr ) { return val * index }) console .log(arr) console .log(newArr)
map()
就是加强版的 forEach()
,所以实现方法大致相同,只是多了一个返回新数组,实现如下
Array .prototype.myMap = function (fn, callback ) { var arr = [] for (var i = 0 , len = this .length; i < len; i ++) { arr.push(fn.call(callback, this [i], i, this )) } return arr }
filter()
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
filter 过滤,透过;顾名思义,filter()
就是过滤元素的方法,返回一个由过滤的元素组成的新数组。用法如下
var arr = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]var newArr = arr.filter(function (val, index, arr ) { return (val % 2 == 0 ) }) console .log(arr) console .log(newArr)
filter()
方法实现的重点就在于理解 return 返回值的真假决定了正在遍历的该元素是否加入新数组。在实现过程中用到了push()
方法,此方法会在后面详细介绍。
Array .prototype.myFilter = function (fn, callback ) { var arr = [] if (typeof fn === 'function' ) { for (var k = 0 , length3 = this .length; k < length3; k++){ fn.call(callback, this [k], k, this ) && arr.push(this [k]) } } return arr }
some()
some()
方法用于检测数组中的元素是否满足指定条件(函数提供)。
some 一些。some()
就是当数组中只要有一个元素符合条件就返回真。用法如下
var arr = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]var flag = arr.some(function (val, index, arr ) { return val === 5 }) console .log(flag)
some()
看起来用法和上面的几种差不多,实现起来自然也不会有太大差别,仅仅是多了一层 if 判断,判断是否符合条件,实现如下
Array .prototype.mySome = function (fn, callback ) { var flag = false if (typeof fn === 'function' ) { for (var j = 0 , length2 = this .length; j < length2; j++){ if (flag == true ) { break } flag = !! fn.call(callback, this [j], j, this ) } } return flag }
every()
every()
方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every 所以。说到some,自然离不开every。every就是判断数组中是否所有的元素都满足条件,一旦有一个不满足就返回 false,用法如下
var arr = [-1 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ]var flag = arr.every(function (val ,index, arr ) { return val > 0 }) console .log(flag) every() 与 some() 的实现方法相似,只有在真假的判断上有些许区别,不多说,直接看代码 Array .prototype.myEvery = function (fn, callback ) { var flag = true if (typeof fn === 'function' ) { for (var j = 0 , length2 = this .length; j < length2; j++){ if (flag === false ) { break } flag = !!fn.call(callback, this [j], j, this ) } } return flag }
copyWithin()
copyWithin()
方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。
copyWithin 看名字组成,就是数组内部的拷贝,相当于选择其中的一部分元素复制,粘贴到另一部分去,这就是一个用法不同于上面所说的通式的方法了。值得注意的地方是,此方法会改变原数组的元素,但不改变其大小。他的参数列表及用法如下
arr.copyWithin(target, start, end) var arr = [1 , 2 , 3 , 4 , 5 , 6 , 7 ]console .log(arr.copyWithin(3 )) console .log(arr.copyWithin(3 , 1 )) console .log(arr.copyWithin(3 , 2 , 5 )) console .log(arr.copyWithin(3 , 4 , 8 )) console .log(arr.copyWithin(3 , 4 , -2 ))
第一次看到这个,肯定是看的头大吧, 不过没关系,接下来一步一步剖析整个过程
var arr = [1 , 2 , 3 , 4 , 5 , 6 , 7 ]console .log(arr.copyWithin(3 )) console .log(arr.copyWithin(3 , 1 )) console .log(arr.copyWithin(3 , 2 , 5 )) console .log(arr.copyWithin(3 , 4 , 8 )) console .log(arr.copyWithin(3 , 4 , -2 ))
看到这里相信你已经看懂了吧,会用了,下一步就是自己实现了,上面的过程基本也介绍了整个过程,就是首先确定 start 与 end ,然后根据二者的值确定要复制的数组片段,再根据 target 确定从何处开始复制。下面就是自己的实现
Array .prototype.myCopyWithin = function (target, start, end ) { var arr = this , len = this .length var start = start || 0 var end = end || len end = end > len ? len : (end < 0 ? len + end : end) var clArr = [] var index = start, len2 = end - start for ( var i = 0 ; i < len2; i ++) { clArr[i] = this [index] index ++ } index = 0 var len3 = target + len2 len3 = len3 > len ? len : len3 for ( var j = target; j < len3; j ++) { arr[j] = clArr[index] index ++ } return arr }
fill()
fill()
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
fill 填充,一个和 copyWithin()
类似的方法,因为他们都是往数组里面填充一个片段,不同的是一个填充的是本来的数组的内容,一个填充的是一个固定值。其参数列表与用法如下
arr.fill(val, start, end) var arr = [1 , 2 , 3 , 4 , 5 , 6 , 7 ]console .log(arr.fill(5 , 0 , 3 )) console .log(arr.fill(3 , 5 )) console .log(arr.fill(6 ))
用法看起来也是一目了然,实现起来也是很容易,实现如下
Array .prototype.myFill = function ( ) { var arr = this var val = arguments [0 ], start = arguments [1 ] || 0 , end = arguments [2 ] || arr.length for (var i = start; i < end; i ++) { arr[i] = val } return arr }
concat()
concat()
方法用于连接两个或多个数组。
concat 合并多个数组,就是将传入的多个数组按顺序连接在目标数组后面,并且返回新数组 ,参数列表及用法如下
arr.concat(arr1, arr2, ...arrN) var arr1 = [1 , 2 , 3 , 4 ]var arr2 = [2 , 3 , 4 , 5 ]var arr3 = [3 , 4 , 5 , 6 ]var num1 = 7 var newArr1 = arr1.concat(arr2, arr3)var newArr2 = arr1.concat(arr2)var newArr3 = arr1.concat(num1)console .log(newArr1) console .log(newArr2) console .log(newArr3)
此方法就是首先复制一个原数组的副本,然后将要连接的数组(数值)都拼接到后面,实现起来也很简单
Array .prototype.myConcat = function ( ) { var arr = this var len = arguments .length for (let i = 0 ; i < len; i ++ ) { if (Object .prototype.toString.call(arguments [i]) === '[object Array]' ) { var len2 = arguments [i].length for (let j = 0 ; j < len2; j ++) { arr[arr.length] = arguments [i][j] } } else { arr[arr.length] = arguments [i] } } return arr }