從 forEach 開始談?wù)劚闅v技巧
forEach
今天從 forEach 開始談?wù)劚闅v吧。
forEach 作為一個比較出眾的遍歷操作,之前有很多庫都對其進(jìn)行過各種包裝,然而我還是發(fā)現(xiàn)很多人并不是非常理解 forEach。
比如第二個參數(shù) this 的使用。
往常都習(xí)慣這么做:
- const self = this
- arr.forEach(function(item) {
- // do something with this
- })
然而如果使用第二個參數(shù)就可以這樣:
- arr.forEach(function(item) {
- // do something with this
- }, this)
省去了一個中間的self,看起來更優(yōu)美了
那么有沒有更好的處理方式呢?
有的:
- arr.forEach(item => {
- // do something
- })
由于 arrow function 的特性,自動綁定父 scope 的 this, 會更加簡潔,而且少了個function關(guān)鍵字,可讀性更好。
for
說到循環(huán)必定要說到for循環(huán)了。js里面的for循環(huán)有好幾種使用方式:
C 系列 for 循環(huán):
- for (let index = 0; index < arr.length; index++) {
- // do something
- }
index 是 arr 的索引,在循環(huán)體中通過 arr[index] 調(diào)用當(dāng)前的元素,我非常不喜歡這種方式,因?yàn)橐獙憙蓚€分號!
還有另一種比較簡單的方式:
- for (let key in obj) {
- // do something
- }
不過這個方式一般用來遍歷對象,下文有說。
關(guān)于 for 循環(huán)還有 ES2015 規(guī)定的一種
- for (let item of arr) {
- // do something
- }
這種遍歷方式和之前的***區(qū)別在于item,它是value而非key,可以直接迭代出內(nèi)容。
不過這種方式我個人用的不多,因?yàn)楹芏嗲闆r下我更喜歡用array下的方法。對于對象的遍歷更傾向于for...in
map 系列
這一塊是js的函數(shù)式領(lǐng)域了。
Array.prototype下掛載著幾個非常好用的遍歷函數(shù)。比如map
它會遍歷arr下的所有內(nèi)容,做操作之后返回數(shù)據(jù),形成一個新的數(shù)組:
- const arr = [1, 2, 3]
- arr.map(current => current * 5)
在 react 最常用。經(jīng)常用來遍歷數(shù)據(jù),形成dom:
- someRender() {
- return this.state.data.map((current, index) => {
- return <li key={index}>{ current }</li>
- })
- }
不過 map 有一點(diǎn)不好的地方在于不能控制循環(huán)的流程,如果不能完成,就返回undefined繼續(xù)下一次迭代。所以遇到可能會返回undefined的情況應(yīng)該用forEach或者for循環(huán)遍歷
還有filter用法和map一模一樣,只是它用來過濾數(shù)據(jù)。非常的好用。
arguments
說到遍歷不得不提及arguments, 在function()中的所有參數(shù),奇怪的是它并不是一個數(shù)組。只是一個類數(shù)組。
一般需要轉(zhuǎn)成數(shù)組:
- function foo() {
- const args = Array.prototype.slice.call(arguments)
- return Array.isArray(args)
- }
但是我個人并不認(rèn)同這樣的方法,有了新的 ES2015 就不要用這么丑的語法了
- function foo(...args) {
- // args 是數(shù)組
- }
ES2015 的 rest 語法使得剩余參數(shù)都傳入args里面,比之前的還要調(diào)Array的方法要輕松不少。
object
對象的遍歷是非常常用的功能。
我個人更喜歡用for...in語法,但是有一點(diǎn)需要注意:
- for (let index in obj) {
- if(obj.hasOwnProperty(index)) {
- // do something
- }
- }
因?yàn)槌菑?qiáng)制指定,否則對象都是不純凈的。都會有__proto__屬性,也會被迭代出來。需要過濾一下。
好了,如何創(chuàng)建純凈的對象?
- const plainObj = Object.create(null)
最輕的obj結(jié)構(gòu),內(nèi)部沒有任何多余的屬性。