主要有:isArray reduce flat forEach some every filter map 等 Array 方法。
map, filter, reduce 各自有什么作用 map 的作用是生成一个新数组,遍历原数组,将每个元素拿出来做一些变换然后放入到新的数组中。
1 [1 , 2 , 3 ].map(v => v + 1 )
另外 map 的回调函数接受三个参数,分别是当前索引元素,索引,原数组
1 ['1' ,'2' ,'3' ].map(parseInt )
第一轮遍历 parseInt('1', 0) -> 1
第二轮遍历 parseInt('2', 1) -> NaN
第三轮遍历 parseInt('3', 2) -> NaN
filter 的作用也是生成一个新数组,在遍历数组的时候将返回值为 true 的元素放入新数组,我们可以利用这个函数删除一些不需要的元素
1 2 3 let array = [1 , 2 , 4 , 6 ]let newArray = array.filter(item => item !== 6 )console .log(newArray)
和 map 一样,filter 的回调函数也接受三个参数,用处也相同。
reduce 可以将数组中的元素通过回调函数最终转换为一个值。
对于 reduce 来说,它接受两个参数,分别是回调函数和初始值。
回调函数 接受四个参数,分别为累计值、当前元素、当前索引、原数组 。
接下来我们就通过 reduce 来实现 map 函数:
1 2 3 4 5 6 7 const arr = [1 , 2 , 3 ]const mapArray = arr.map(value => value * 2 )const reduceArray = arr.reduce((acc, current ) => { acc.push(current * 2 ) return acc }, []) console .log(mapArray, reduceArray)
Array.isArray 实现 可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString()
来检测,需要以 Function.prototype.call()
或者 Function.prototype.apply()
的形式来调用,传递要检查的对象作为第一个参数。
1 2 3 4 Array .myIsArray = function (o ) { return Object .prototype.toString.call(o) === "[object Array]" ; }; console .log(Array .myIsArray([]));
Array.prototype.reduce 实现 reduce() 方法对数组中的每个元素执行一个由您提供的reducer
函数(升序执行),将其结果汇总为单个返回值。由 reduce 返回的值将是最后一次回调返回值。语法:
1 arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
callback
accumulator 累计器
currentValue 当前值
currentIndex 当前索引,可选
array 数组,可选
initialValue 可选,作为第一次调用 callback 函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。
栗子 求数组之和:
1 2 const array1 = [1 , 2 , 3 , 4 ];let result = array1.reduce((prev, curr ) => prev + curr);
数组去重:
1 2 3 4 5 6 7 8 let arr = [1 , 2 , 1 , 2 , 3 , 5 , 4 , 5 , 3 , 4 , 4 , 4 , 4 ];let result = arr.sort().reduce((init, current ) => { if (init.length === 0 || init[init.length - 1 ] !== current) { init.push(current); } return init; }, []); console .log(result);
按顺序运行 Promise:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function runPromiseInSequence (arr, input ) { return arr.reduce( (promiseChain, currentFunction) => promiseChain.then(currentFunction), Promise .resolve(input) ); } function p1 (a ) { return new Promise ((resolve, reject ) => { resolve(a * 5 ); }); } const promiseArr = [p1, p2, f3, p4];runPromiseInSequence(promiseArr, 10 ).then(console .log);
功能型函数管道:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const double = x => x + x;const triple = x => 3 * x;const pipe = (...functions ) => input => functions.reduce((acc, fn ) => fn(acc), input); const pipe = function (...functions ) { return function (input ) { return functions.reduce(function (acc, fn ) { return fn(acc); }, input); }; }; const multiply6 = pipe(double, triple);multiply6(6 );
模拟实现 第一版:
1 2 3 4 5 6 7 8 9 10 11 Array .prototype.myreduce = function (callback, initialValue ) { const _this = this ; let accumulator = initialValue ? initialValue : this [0 ]; for (let i = initialValue ? 0 : 1 ; i < this .length; i++) { accumulator = callback(accumulator, this [i], i, _this); } return accumulator; };
第二版:
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 Array .prototype.myreduce = function reduce (callbackfn ) { const O = this ; const len = O.length >>> 0 ; let k = 0 , accumulator = undefined , kPresent = false , initialValue = arguments .length > 1 ? arguments [1 ] : undefined ; if (typeof callbackfn !== "function" ) { thrownewTypeError(callbackfn + " is not a function" ); } if (len === 0 && arguments .length < 2 ) { thrownewTypeError("Reduce of empty array with no initial value" ); } if (arguments .length > 1 ) { accumulator = initialValue; } else { accumulator = O[k++]; } while (k < len) { kPresent = O.hasOwnProperty(k); if (kPresent) { const kValue = O[k]; accumulator = callbackfn(accumulator, kValue, k, O); } k++; } return accumulator; };
Array.prototype.flat 实现 flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
1 2 3 4 5 6 var newArray = arr.flat([depth]);
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var arr = [1 , 2 , [3 , 4 ]];arr.flat(); arr.reduce((acc, val ) => acc.concat(val), []); const flattened = arr => [].concat(...arr);arr.flat(2 ); arr.flat(Infinity );
使用 reduce 、concat 和递归 展开无限多层嵌套的数组:
1 2 3 4 5 6 7 8 9 function flatDeep (arr, d = 1 ) { return d > 0 ? arr.reduce( (acc, val) => acc.concat(Array .isArray(val) ? flatDeep(val, d - 1 ) : val), [] ) : arr.slice(); }
forEach :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const eachFlat = (arr = [], depth = 1 ) => { const result = []; (function flat (arr, depth ) { arr.forEach(item => { if (Array .isArray(item) && depth > 0 ) { flat(item, depth - 1 ); } else { result.push(item); } }); })(arr, depth); return result; }; eachFlat([1 , 2 , [3 , [4 , [5 ]]]], Infinity );
for…of :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const forFlat = (arr = [], depth = 1 ) => { const result = []; (function flat (arr, depth ) { for (let item of arr) { if (Array .isArray(item) && depth > 0 ) { flat(item, depth - 1 ); } else { item !== void 0 && result.push(item); } } })(arr, depth); return result; };
其他方法见MDN 。
Array.prototype.forEach 实现 forEach() 方法对数组的每个元素执行一次给定的函数。语法:
1 arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
forEach()
为每个数组元素执行一次 callback 函数;与 map()
或者 reduce()
不同的是,它总是返回 undefined 值,并且不可链式调用。
例子:对象复制器函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function copy (obj ) { const copy = Object .create(Object .getPrototypeOf(obj)); const propNames = Object .getOwnPropertyNames(obj); propNames.forEach(function (name ) { const desc = Object .getOwnPropertyDescriptor(obj, name); Object .defineProperty(copy, name, desc); }); return copy; } const obj1 = { a : 1 , b : 2 };const obj2 = copy(obj1);
模拟实现:
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 Array .prototype.myforEach = function (callback, thisArg ) { var k, T; if (this == null ) { throw new TypeError (" this is null or not defined" ); } var O = Object (this ); var len = O.length >>> 0 ; if (typeof callback !== "function" ) { throw new TypeError (callback + " is not a function" ); } if (arguments .length > 1 ) { T = thisArg; } k = 0 ; while (k < len) { var kValue; if (k in O) { kValue = O[k]; callback.call(T, kValue, k, O); } k++; } };
Array.prototype.every 实现 every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
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 if (!Array .prototype.every) { Array .prototype.every = function (callbackfn, thisArg ) { "use strict" ; var T, k; if (this == null ) { throw new TypeError ("this is null or not defined" ); } var O = Object (this ); var len = O.length >>> 0 ; if (typeof callbackfn !== "function" ) { throw new TypeError (); } if (arguments .length > 1 ) { T = thisArg; } k = 0 ; while (k < len) { var kValue; if (k in O) { kValue = O[k]; var testResult = callbackfn.call(T, kValue, k, O); if (!testResult) { return false ; } } k++; } return true ; }; }
Array.prototype.some 实现 some() 方法测试数组中是不是至少有 1 个元素通过了被提供的函数测试。它返回的是一个 Boolean 类型的值。
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 if (!Array .prototype.some) { Array .prototype.some = function (fun /*, thisArg*/ ) { "use strict" ; if (this == null ) { throw new TypeError ("Array.prototype.some called on null or undefined" ); } if (typeof fun !== "function" ) { throw new TypeError (); } var t = Object (this ); var len = t.length >>> 0 ; var thisArg = arguments .length >= 2 ? arguments [1 ] : void 0 ; for (var i = 0 ; i < len; i++) { if (i in t && fun.call(thisArg, t[i], i, t)) { return true ; } } return false ; }; }
Array.prototype.map 实现 map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。
用法:
1 2 3 4 ["1" , "2" , "3" ].map(parseInt ); ["1" , "2" , "3" ].map(str => parseInt (str));
Plyfill:
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 if (!Array .prototype.map) { Array .prototype.map = function (callback /*, thisArg*/ ) { var T, A, k; if (this == null ) { throw new TypeError ("this is null or not defined" ); } var O = Object (this ); var len = O.length >>> 0 ; if (typeof callback !== "function" ) { throw new TypeError (callback + " is not a function" ); } if (arguments .length > 1 ) { T = arguments [1 ]; } A = new Array (len); k = 0 ; while (k < len) { var kValue, mappedValue; if (k in O) { kValue = O[k]; mappedValue = callback.call(T, kValue, k, O); A[k] = mappedValue; } k++; } return A; }; }
Array.prototype.filter 实现 filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或等价于 true 的值的元素创建一个新数组。
用法:
1 2 3 4 5 6 7 8 9 10 const fruits = ["apple" , "banana" , "grapes" , "mango" , "orange" ];const filterItems = query => { return fruits.filter( el => el.toLowerCase().indexOf(query.toLowerCase()) > -1 ); }; console .log(filterItems("ap" )); console .log(filterItems("an" ));
Polyfill:
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 if (!Array .prototype.filter) { Array .prototype.filter = function (func /*, thisArg*/ ) { "use strict" ; if (!((typeof func === "Function" || typeof func === "function" ) && this )) throw new TypeError (); var len = this .length >>> 0 , res = new Array (len), t = this , c = 0 , i = -1 , T; if (arguments .length > 1 ) { T = arguments [1 ]; } while (++i !== len) { if (i in this ) { if (func.call(T, t[i], i, t)) { res[c++] = t[i]; } } } res.length = c; return res; }; }
Array 迭代方法
Array.prototype.forEach()
为数组中的每个元素执行一次回调函数。
Array.prototype.entries()
返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。
Array.prototype.every()
如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。
Array.prototype.some()
如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。
Array.prototype.filter()
将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。
Array.prototype.find()
找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 undefined。
Array.prototype.findIndex()
找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 -1。
Array.prototype.keys()
返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。
Array.prototype.map()
返回一个由回调函数的返回值组成的新数组。
Array.prototype.reduce()
从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
Array.prototype.reduceRight()
从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
Array.prototype.values()
返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。
Array.prototype[@@iterator]()
和上面的 values() 方法是同一个函数。