[【第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);
~~~

- 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