以前翻譯過一篇文章,《我喜歡的5個編程技巧》,裏面的一個技巧是借鑑一個網站的代碼片斷,好奇的小手點下連接後,發現是一個有 47000
多star的倉庫,30-seconds-of-code。javascript
倉庫的名字就讓我很驚訝,30秒就能理解一段代碼,有點難以想象。看了每一個方法實現的代碼都不長,很簡短,最複雜的也不過是四、5行代碼,的確沒有標題黨的嫌疑,滿滿的幹活。css
處理的類型還很豐富,有Array、Browser、Date、Function、Math、Node、Object、String、Type、Utility。要了解更多,戳這裏。前端
這就是一個工具函數庫呀。java
此時讓我想到了 lodash.js
和 underscore.js
,用過這兩個函數式編程的庫,對提供的方法確定不陌生。它們主要是以函數做爲主要載體的編程方式,用函數去拆解、抽象的表達式,每一個函數封裝特定的功能,做用域侷限在函數內部,造成閉包,不對外界產生反作用。react
相信也有不少人閱讀過它們的源碼,每一個函數很簡短,考慮到兼容性,基本都用原生的方式實現,不會調用一些規範中最新推出的方法。若是可以精讀它們,對本身的編程能力會有更高的提高,可以掌握不少的技巧。有時你可能只是想快速的瞭解一個方法大體的實現原理,但要去看源碼的話,仍是會有一些門檻。git
而這個30秒就能理解的代碼片斷,摒棄了許多沒必要要的代碼,只實現了最核心的部分,不像 lodash.js
和 underscore.js
那樣,考慮參數邊界值問題,例如,參數的類型是否符合預期等。默認狀況下,都是按照傳遞符合預期的參數處理。github
若是要把這個庫用在本身的項目中,沒有對參數的判斷是很是糟糕的一件事。但不想引 lodash.js
或 underscore.js
這樣大的庫文件,想本身實現一個簡潔的方法快速使用,那麼這個庫會對你實現本身的方法具備指導意義。不考慮兼容問題的話,你能夠直接拷貝這個庫的代碼片斷,加上對參數邊界的處理就直接能用。編程
再有一點,這個庫之因此簡短,可以讓你在30秒就理解,主要是能用規範提供的最新方法就用,再也不很費勁的本身實現一套,全都調用了原生提供的方法,包括 ES6
的方法。每一個方法都是獨立的,可獨立測試,獨立運行,和其餘的方法互不牽扯,極大的下降了閱讀時找各類方法會被打斷思路的煩惱。segmentfault
固然,若是你想閱讀 lodash.js
或 underscore.js
的源碼,先閱讀這個庫會頗有幫助,它排除了許多沒必要要的干擾讓你很清晰很明確的get到核心的實現方式。數組
以前也有人翻譯過,但都很早,大約2年前了,做者最新最近更新的方法都沒有。並且倉庫中不止提供 javascript
的方法,還有 css
react
的簡短代碼,還有其餘語言的。基於本身學習的目的,同時也讓更多人掌握這些方法的實現方式,決定翻譯成中文。
倉庫地址:https://github.com/WYseven/30-seconds-of-code。感興趣的,能夠給個 star 哦!
目前已完成數組方法的翻譯,點擊查看 https://wyseven.github.io/30-seconds-of-code/。其餘方法也在持續的更新中。。。
我不建議你悶着頭一口氣讀完,而後頭昏眼花的不知道本身看了什麼。而是建議你在閒暇之餘,工做空隙,斷斷續續,一天看幾個就夠了,權當作工做累了休憩時當作消遣來看。
由於篇幅的緣由,如下隨機選擇了10個方法,你看簡單不簡單。
chunk
deepFlatten
flatten
initialize2DArray
union
mapObject
pull
reducedFilter
xProd
將數組分塊成指定大小的較小數組。
使用 array.from()
建立一個新的數組,該數組的長度就是將要生成的塊(chunk)的個數。
使用 array.prototype.slice()
將新數組的每一個元素映射爲一個長度爲 size
的塊(chunk)。
若是原始數組不能被平均分割,那麼最後的塊(chunk)將包含剩餘的元素。
const chunk = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size) );
chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
深度平鋪一個數組。
使用遞歸。
使用 array. prototype.concat()
和空數組( []
),結合 spread 操做符('...')將數組平鋪。
遞歸平鋪數組中的每一個元素。
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]
將數組展平到指定的深度。
使用遞歸,爲每一個深度級別 depth
遞減 1
。 使用 Array.prototype.reduce()
和 Array.prototype.concat()
來合併元素或數組。 基本狀況下,depth
等於 1
中止遞歸。 省略第二個參數,depth
只能平鋪到 1
層(單層平鋪) 的深度。
const flatten = (arr, depth = 1) => arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
flatten([1, [2], 3, 4]); // [1, 2, 3, 4] flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
初始化一個給定行數和列數,以及值的二維數組。
使用 array.prototype.map()
生成 h
行,其中每一行都是長度爲 w
的新數組。若是沒有提供值 val
,則默認爲 null
。
const initialize2DArray = (w, h, val = null) => Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
initialize2DArray(2, 2, 0); // [[0,0], [0,0]]
返回兩個數組的並集,相同的元素只出現一次。
基於 a
和 b
建立一個 Set
對象,返回轉換後的數組。
const union = (a, b) => Array.from(new Set([...a, ...b]));
union([1, 2, 3], [4, 3, 2]); // [1,2,3,4]
使用一個函數將數組的值映射到對象,在鍵值對中,原始值做爲鍵,映射值做爲值。
使用一個匿名的內部函數做用域來聲明一個 undefined 的內存空間,使用閉包來存儲返回值。 使用一個新的 Array
來存儲帶有函數映射的數組和一個逗號運算符來返回第二個步驟,而不須要從一個上下文移動到另外一個上下文(因爲閉包和操做順序)。
const mapObject = (arr, fn) => (a => ( (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) ))();
const squareIt = arr => mapObject(arr, a => a * a); squareIt([1, 2, 3]); // { 1: 1, 2: 4, 3: 9 }
將指定數量的元素移動到數組的末尾。
兩次使用 Array.prototype.slice()
來獲取指定索引以後的元素和指定索引以前的元素。
使用展開操做符(...
)將兩個數組合成一個數組。
若是 offset
爲負數,元素將從結束移動到開始位置。
const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
offset([1, 2, 3, 4, 5], 2); // [3, 4, 5, 1, 2] offset([1, 2, 3, 4, 5], -2); // [4, 5, 1, 2, 3]
改變原始數組,過濾掉指定的值。
使用 Array.prototype.filter()
和 array.prototype.include()
過濾指定的值。
使用 Array.prototype.length = 0
經過將數組的長度重置爲0來清空數組,並使用 array.prototype.push()
把提取的值從新填充數組。
(對於不改變原始數組的代碼片斷,請參閱 without
)
const pull = (arr, ...args) => { let argState = Array.isArray(args[0]) ? args[0] : args; let pulled = arr.filter((v, i) => !argState.includes(v)); arr.length = 0; pulled.forEach(v => arr.push(v)); };
let myArray = ['a', 'b', 'c', 'a', 'b', 'c']; pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ]
根據條件過濾一個對象數組,同時過濾掉未指定的鍵。
使用 array.prototype.filter()
根據斷言函數 fn
對數組進行過濾,返回條件爲真值(truthy)的對象。
在通過過濾後的數組上,使用 array.prototype.map()
和 array.prototype.reduce()
過濾掉在 keys
參數中未提供的鍵。
const reducedFilter = (data, keys, fn) => data.filter(fn).map(el => keys.reduce((acc, key) => { acc[key] = el[key]; return acc; }, {}) );
const data = [ { id: 1, name: 'john', age: 24 }, { id: 2, name: 'mike', age: 50 } ]; reducedFilter(data, ['id', 'name'], item => item.age > 24); // [{ id: 2, name: 'mike'}]
將兩個數組的每一個元素兩兩進行組合,組合出全部的可能對存在數組中,返回一個存在全部可能性對的數組。
使用 Array.prototype.reduce()
, Array.prototype.map()
和 Array.prototype.concat()
從兩個數組的元素中生成全部可能的對,並將它們保存在一個數組中。
const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
xProd([1, 2], ['a', 'b']); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
看完後,是否是以爲實現特簡潔特簡單?
看完後,給個 star 哦!倉庫地址:https://github.com/WYseven/30...。
若是對你有幫助,請關注【前端技能解鎖】: