[【第1352期】map和reduce,处理数据结构的利器](https://mp.weixin.qq.com/s/QEwb3hL0k95bOC1OPfENwQ)
现如今JavaScript有许多问题,但是词法并不是其中之一。不管是三元运算符,还是map/reduce等ES6方法,亦或是扩展运算符(…)都是非常强大的工具。
除了能够保证可读性以及准确性,这些方法还有助于实现不可变性,因为这些方法会返回新的数据,而处理前的原始数据并不会被修改。这样的处理风格很适合redux以及Fractal。
一个简单的reduce实践
当你想要将多个数据放进一个实例中时,你可以使用一个reducer。
~~~
const posts = [
{id: 1, upVotes: 2},
{id: 2, upVotes: 89},
{id: 3, upVotes: 1}
];
const totalUpvotes = posts.reduce(totalUpvotes,currentPost)=>{
totalUpvotes + currentPost.upVotes,
0
}
console.log(totalUpvotes)
~~~
传给reduce的第一个参数函数还可以增加2个参数:
* 第三个参数:每个元素在原数据结构中的位置,比如数组下标。
* 第四个参数:调用reduce方法的数据集合,比如例子中的posts。
所以,一个reducer的完全体应该是下面这样的
~~~
collection.reduce(
(accumulator, currentElement, currentIndex, collectionCopy) =>
{/*function body*/},
initialAccumulatorValue);
~~~
### 一个简单的map实践
map方法的作用在于处理流式数据,比如数组。我们可以把它想象成所有元素都要经过的一个转换器。
~~~
const integers = [1, 2, 3, 4, 6, 7];
const twoXIntegers = integers.map(i => i*2);
// twoXIntegers现在是 [2, 4, 6, 8, 12, 14],而integers不发生变化。
~~~
### 一个简单的find实践
find返回数组或类似结构中满足条件的第一个元素。
~~~
const posts = [
{id: 1, title: 'Title 1'},
{id: 2, title: 'Title 2'}
];
// 找出id为1的posts
const title = posts.find(p => p.id ===1).title
~~~
### 一个简单的filter实践
filter方法可以筛除数组和类似结构中不满足条件的元素,并返回满足条件的元素组成的数组。
~~~
const integers = [1, 2, 3, 4, 6, 7];
const evenintergers = integers.filter( i => i % 2 ===0)
~~~
### 向数组中新增元素
如果你要创建一个无限滚动的ui组件(比如本文后面提到的例子),可以使用扩展运算符这个非常有用的词法。
~~~
const books = ['Positioning by Trout', 'War by Green'];
const newbooks = [...books, 'hhshshsh'];
// newBooks are now ['Positioning by Trout', 'War by Green', 'HWFIF // by Carnegie']
~~~
### 为一个数组创建视图
如果需要实现用户从购物车中删除物品,但是又不想破坏原来的购物车列表,可以使用filter方法。
~~~
const myId = 6;
const userIds = [1, 5, 7, 3, 6];
const allButMe = userIds.filter(id => id !== myId);
// allButMe is [1, 5, 7, 3]
~~~
### 向对象数组添加新元素
~~~
const books = [];
const newBook = {title: 'Alice in wonderland', id: 1};
const updatedBooks = [...books, newBook];
//updatedBooks的值为[{title: 'Alice in wonderland', id: 1}]
~~~
books这个变量我们没有给出定义,但是不要紧,我们使用了扩展运算符,它并不会因此失效。
### 为对象新增一组键值对
~~~
const user = {name: 'Shivek Khurana'};
const updatedUser = {...user, age: 23};
//updatedUser的值为:{name: 'Shivek Khurana', age: 23}
~~~
### 使用变量作为键名为对象添加键值对
~~~
const dynamicKey = 'wearsSpectacles';
const user = {name: 'Shivek Khurana'};
const updatedUser = {...user, [dynamicKey]: true};
// updatedUser is {name: 'Shivek Khurana', wearsSpectacles: true}
~~~
### 修改数组中满足条件的元素对象
~~~
const posts = [
{id: 1, title: 'Title 1'},
{id: 2, title: 'Title 2'}
];
const updatedPosts = posts.map(p => p.id !== 1 ?
p : {...p, title: 'Updated Title 1'}
);
/*
updatedPosts is now
[
{id: 1, title: 'Updated Title 1'},
{id: 2, title: 'Title 2'}
];
*/
~~~
### 删除目标对象的一组属性
~~~
const user = {name: 'Shivek Khurana', age: 23, password: 'SantaCl@use'};
const userWithoutPassword = Object.keys(user)
.filter(key => key !== 'password')
.map(key => {[key]: user[key]})
.reduce((accumulator, current) =>
({...accumulator, ...current}),
{}
)
;
// userWithoutPassword becomes {name: 'Shivek Khurana', age: 23}
~~~
感谢Kevin Bradley提供了一个更优雅的方法:
~~~
const user = {name: 'Shivek Khurana', age: 23, password: 'SantaCl@use'};
const userWithoutPassword = (({name, age}) => ({name, age}))(user);
~~~
### 将对象转化成请求串
你也许几乎遇不到这个需求,但是有时候在别的地方会给你一点启发。
~~~
const params = {color: 'red', minPrice: 8000, maxPrice: 10000};
const query = '?' + Object.keys(params)
.map(k =>
encodeURIComponent(k) + '=' + encodeURIComponent(params[k])
)
.join('&')
;
// encodeURIComponent将对特殊字符进行编码。
// query is now "color=red&minPrice=8000&maxPrice=10000"
~~~
### 获取数组中某一对象的下标
~~~
const posts = [
{id: 13, title: 'Title 221'},
{id: 5, title: 'Title 102'},
{id: 131, title: 'Title 18'},
{id: 55, title: 'Title 234'}
];
// 找到id为131的元素
const requiredIndex = posts.map(p => p.id).indexOf(131);
~~~
![](https://box.kancloud.cn/46bea5cc0883b3db7602422bfd664402_1144x486.png)
- js
- js继承
- keyCode
- 好的网站
- 零散知识点-js
- This
- 对象深拷贝和浅拷贝
- 数组方法
- 数组的深拷贝和浅拷贝
- JS 引擎的执行机制
- js中的new
- 常用正则
- 函数柯里化
- 会修改当前数组的方法
- 不会修改当前数组的方法
- 函数式编程
- 循环遍历
- 基础知识
- 异步
- js知识总结
- fileReader
- HTML
- 零散知识点
- html5新特性
- viewport
- CSS
- cursor
- css3新特性
- 水平居中
- 垂直居中
- display解析
- 块级元素和行内元素
- css技巧和方法
- 清除浮动
- Less
- Sass
- 综合
- 微信小程序
- 前端面试
- CSS-面试
- JS-面试
- js-web-api
- js知识
- MVC-面试
- jQuery与框架的区别
- 闭包
- promise
- http状态码
- cdn
- 离线存储
- 事件
- web安全
- 性能优化
- 响应式
- 服务器渲染和本地渲染
- 模板是什么?
- VUE流程
- 浏览器渲染过程
- this的指向
- new的使用
- HTML-面试
- title和alt区别
- html5元素
- h5新特性
- 图片格式
- 零散面试总结
- react
- 生命周期-react
- state
- props
- 组件通信
- 虚拟DOM
- 源码分析
- webstorm-template
- element与component区别
- 组件的理解
- JXS
- vue与react区别
- 16.8版本
- vue
- 生命周期-vue
- 实现流程
- webpack
- 概念
- 入口起点
- 出口
- loader
- 模式
- 插件
- manifest
- redux
- 介绍
- 核心概念
- 三大原则
- 基础
- action
- reducer
- store
- 数据流
- 高级
- 异步action
- 异步数据流
- middleware
- ES6阮一峰
- ...
- let
- es6箭头函数
- const
- 块级作用域
- 顶层对象的属性
- global 对象
- 变量的解构赋值
- 字符串的扩展
- promise对象
- 正则的扩展
- 数值的扩展
- Math对象的扩展
- 函数的扩展
- 数组的扩展
- 对象的扩展
- symbol
- async函数
- class的基本用法
- Class 的继承
- Set 和 Map 数据结构
- 开发工具
- 好用的软件
- chrome插件
- 其他实用工具
- 微信公众号-前端早读课
- 【第1352期】map和reduce,处理数据结构的利器
- 微信公众号-前端大全
- JS 的执行机制
- 一篇文章理解 JS 继承
- 浏览器
- 缓存
- 《Webkit技术内幕》之页面渲染过程
- 跨域
- 安全
- XSS
- 设计模式
- 发布订阅模式
- 工厂模式
- MV*模式
- 观察者模式
- react-router
- 一些小技巧
- js一些小算法
- 1.已知一个数组中的值,在另外一个数组中查找该值
- 累加器
- 数组随机
- 数组扁平化并去重排序
- Immutable
- 常用命令
- hybrid
- schema封装
- typescript