Array.reduce()方法的使用
起因是学习异步函数的串行与并行写法时,发现reduce方法可以简化写法,然后看到一篇博客里面这样一段代码:
var array = [1, [2, [3, 4], 5], 6];
function flatten(array) {
return array.reduce(function (arr, item) {
return (Object.prototype.toString.call(item) === '[object Array]'
? Array.prototype.push.apply(arr, flatten(item))
: arr.push(item)
, arr);
}, []);
}
console.log(flatten(array));
发现好多不理解的地方,花费些许时间终于弄懂了:
- reduce(fn,initValue)接收2个参数。第一个是迭代器函数,函数的作用是对数组中从左到右的每一个元素进行处理。函数有4个参数,分别是accumulator、currentValue、currentIndex、array。
accumulator 累加器,即函数上一次调用的返回值。第一次的时候为 initialValue || arr[0]
currentValue 数组中函数正在处理的的值。第一次的时候initialValue || arr[1]
currentIndex 数组中函数正在处理的的索引
array 函数调用的数组
initValue reduce 的第二个可选参数,累加器的初始值。没有时,累加器第一次的值为currentValue;
2. return (a,b) 这里其实就是逗号运算符了。先计算左边,再计算右边,最后返回右边的值。比如
var n = (1,2,3,4);
console.log(n); //
3. 然后reduce的第一个参数的这个函数一定要每次都有返回值;
4. Array.prototype.push.apply(arr1,arr2)为什么可以把2个数组concat()起来。
我觉得我应该能想的出来的,以前看过但没怎么用,印象不深刻,所以没记起来。
这个从 call 、apply、bind 说起。
fn.call() 第一个参数,传入调用的对象,第二个以后的参数为fn的参数,一一对应;
fn.apply() 同上,第二个参数变为数组,数组中的元素与fn的参数一一对应;
fn.bind() 同 apply ,不过 call apply 直接就执行了, bind 是生成了一个新函数,在需要的时候执行。
这样就出来了, Array.prototype.push.apply(arr1,arr2) 将 arr2 中的每一个元素当成参数 push 到 arr1 中去了,而不是arr1.push(arr2)。
所以上述的意思就是,第一次迭代时 accumulator 的值为[],然后递归调用flatten,每次都返回accumulator
此外 apply 还有很多巧妙的用处,比如数组找最大值Math.max.apply(Math,arr);
伪数组的转换Array.prototype.slice.apply(arguments)
上文说过fn.apply()接收2个参数,一个是context,一个是数组作为参数。此时只传了一个上下文环境(arguments是伪数组,本身没有slice方法,所以借用数组原型上的方法),而slice本身是没有传参数的。不传参数默认为slice(0),即 Array.prototype.slice.apply(arguments,[0])所以就将整个数组复制一份返回出来了。
关于promise
reduce 可以使 promise 的串行.then()写法变得简单;
// promise生成函数
function log(n, delay, param) {
return function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(n);
resolve(param);
}, delay);
})
}
}
/**异步函数的串行1
* 这是正常的promise链式调用,每个then里面都返回一个promise;
* 上一个执行完成,下一个才会执行
*/
Promise.resolve()
.then(log(1,300))
.then(log(2,0))
.then(log(3,500))
.then(log(4,100));
上面的代码按顺序打印出1、2、3、4。
如果想让1、2、3、4全部执行完毕后再执行某个函数,则可以用Promise.all(arr)
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。具体示例如下:
//异步函数的并行写法
Promise.all([
log(1, 300, "aa")(), log(2, 0, "bb")(), log(3, 1500, "cc")(), log(4, 100, "dd")()
]).then((result) => {
console.log('finished!')
console.log(result);
});
//
//
//
//
//finished!
//[ 'aa', 'bb', 'cc', 'dd' ]
如果想让串行的写法和这种并行的写法差不多的话,可以用到reduce()
函数
//异步函数的串行2
//reduce中传入Promise.resolve()作为累加器的初始值
//第一次时Promise.resolve().then(fn)传入一个函数log(1, 300),函数运行后返回promis实例
//这个实例作为第二次的累加器的值,然后调用它的then()方法,并传入数组的第二项...
[log(1, 300),log(2, 0),log(3, 500),log(4, 100)].reduce((accumulator, value) => {
return accumulator.then(value)
},Promise.resolve());
结果和上面的串行1一样,按顺序打印出来1、2、3、4
原文链接:https://blog.csdn.net/q1325545052/article/details/78851786
参考链接:https://blog.csdn.net/zhendong9860/article/details/74908062
Array.reduce()方法的使用的更多相关文章
- Array.reduce()方法
Array.reduce()方法是对数组的遍历,返回一个单个返回值 使用方法: Array.reduce((acc, cur, idx, src) => { }, initialValue) ...
- 用es6的Array.reduce()方法计算一个字符串中每个字符出现的次数
有一道经典的字符串处理的问题,统计一个字符串中每个字符出现的次数. 用es6的Array.reduce()函数配合“...”扩展符号可以更方便的处理该问题. s='abananbaacnncn' [. ...
- Array.reduce()学习
昨天遇到的一道题:1234567890 => 1,234,567,890 要求其实就是使用逗号做千分位将数字进行分隔. 当时没想到任何方法,但是以前看到过,印象很深刻,今天就找了一下. 看到其实 ...
- JS Array.reduce 对象属性累加
Array reduce() 方法 ,无非就是 计算数组元素 相加后的总和 ,看网上给的Demo 全是 [1,2,3,4,6].reduce 这种基本用法, 本次我将使用 reduce 实现 数组 ...
- 自从学会了 Array.reduce() ,再也离不开它
(转载)原文链接:https://juejin.im/post/5dfd9d27e51d455825129ec3 在所有后 ES6 时代的数组方法中,我觉得最难理解的就是Array.reduce( ...
- JavaScript - reduce方法,reduceRight方法 (Array)
JavaScript - reduce方法 (Array) 解释:reduce() 方法接收一个函数作为累加器(accumulator),数组 中的每个值(从左到右)开始合并,最终为一个值. 语法:a ...
- reduce 方法 (Array) (JavaScript)
对数组中的所有元素调用指定的回调函数.该回调函数的返回值为累积结果,并且此返回值在下一次调用该回调函数时作为参数提供. 语法 array1.reduce(callbackfn[, in ...
- 数组的方法之(Array.prototype.reduce() 方法)
reduce函数 reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值. 对数组中的所有元素调用指定的回调函数.该回调函数的返回值为累积结果,并且此返回值在下一次 ...
- JavaScript Array every()&some()&reduce()方法
every()方法测试数组的所有元素是否都通过了指定函数的测试. // 每一项都要满足条件才会返回true,只要有一项不满足返回false var arr = [1, 2, 3, 4]; let bl ...
随机推荐
- Vue.js随笔二(新建路由+component+添加样式+变量的显示)
创建一个页面: 1.首先让我们看一下整个vue.js的目录,如下图所示: 2.现在让我们创建一个页面吧: 2-1首先你需要新建路由(就和建立一个如何找到项目文件的目录一个意思):进入src/route ...
- 【转】手摸手,带你用vue撸后台 系列二(登录权限篇)
前言 拖更有点严重,过了半个月才写了第二篇教程.无奈自己是一个业务猿,每天被我司的产品虐的死去活来,之前又病了一下休息了几天,大家见谅. 进入正题,做后台项目区别于做其它的项目,权限验证与安全性是非常 ...
- HDU 6199 DP 滚动数组
强行卡内存 这题在CF上好像有道极相似的题 可以想到状态设计为dp[f][i][k]表示f在取完i-1时,此时可以取k个或k+1个的状态下的最大值.之前以为n是1e5,自己想不到怎么设计状态真的辣鸡, ...
- [洛谷P1709] [USACO5.5]隐藏口令Hidden Password
洛谷题目链接:[USACO5.5]隐藏口令Hidden Password 题目描述 有时候程序员有很奇怪的方法来隐藏他们的口令.Binny会选择一个字符串S(由N个小写字母组成,5<=N< ...
- CSS进阶知识
html { -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } 该属性的作用是 ...
- LintCode 510: Maximal Rectangle
LintCode 510: Maximal Rectangle 题目描述 给你一个二维矩阵,权值为False和True,找到一个最大的矩形,使得里面的值全部为True,输出它的面积 Wed Nov 2 ...
- 【BZOJ】4318: OSU! 期望DP
[题意]有一个长度为n的01序列,每一段极大的连续1的价值是L^3(长度L).现在给定n个实数表示该位为1的概率,求期望总价值.n<=10^5. [算法]期望DP [题解]后缀长度是一个很关键的 ...
- 深入理解Spring系列之十:DispatcherServlet请求分发源码分析
转载 https://mp.weixin.qq.com/s/-kEjAeQFBYIGb0zRpST4UQ DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请 ...
- 利用PCA可视化异常点
异常点往往是由于某一个特征或者多个特征数值异常.但是对于多维度特征无法直接进行可视化观测异常点,利用PCA技术进行维度缩减,可以在二维或者三维空间上进行可视化展示. 原数据如下: from sklea ...
- PHP 快速建立一个对象
前言 PHP 中的数组(尤其关联数组)是经常使用的 —— 因为方便.在一些框架中也经常见到返回数组格式的配置参数.然而有些时候可能需要对象而非数组类型的配置参数,在查阅网络资料后找到了方法,作以记录. ...