摘要:而這個秒就能理解的代碼片段,摒棄了許多不必要的代碼,只實現了最核心的部分,不像和那樣,考慮參數邊界值問題,例如,參數的類型是否符合預期等。使用根據斷言函數對數組進行過濾,返回條件為真值的對象。
之前翻譯過一篇文章,《我喜歡的5個編程技巧》,里面的一個技巧是借鑒一個網站的代碼片段,好奇的小手點下鏈接后,發現是一個有 47000 多star的倉庫,30-seconds-of-code。
倉庫的名字就讓我很驚訝,30秒就能理解一段代碼,有點不可思議。看了每個方法實現的代碼都不長,很簡短,最復雜的也不過是4、5行代碼,的確沒有標題黨的嫌疑,滿滿的干活。
處理的類型還很豐富,有Array、Browser、Date、Function、Math、Node、Object、String、Type、Utility。要了解更多,戳這里。
這就是一個工具函數庫呀。
此時讓我想到了 lodash.js 和 underscore.js,用過這兩個函數式編程的庫,對提供的方法肯定不陌生。它們主要是以函數作為主要載體的編程方式,用函數去拆解、抽象的表達式,每個函數封裝特定的功能,作用域局限在函數內部,形成閉包,不對外界產生副作用。
相信也有很多人閱讀過它們的源碼,每個函數很簡短,考慮到兼容性,基本都用原生的方式實現,不會調用一些規范中最新推出的方法。如果能夠精讀它們,對自己的編程能力會有更高的提升,能夠掌握很多的技巧。有時你可能只是想快速的了解一個方法大致的實現原理,但要去看源碼的話,還是會有一些門檻。
而這個30秒就能理解的代碼片段,摒棄了許多不必要的代碼,只實現了最核心的部分,不像 lodash.js 和 underscore.js 那樣,考慮參數邊界值問題,例如,參數的類型是否符合預期等。默認情況下,都是按照傳遞符合預期的參數處理。
如果要把這個庫用在自己的項目中,沒有對參數的判斷是非常糟糕的一件事。但不想引 lodash.js 或 underscore.js 這樣大的庫文件,想自己實現一個簡潔的方法快速使用,那么這個庫會對你實現自己的方法具有指導意義。不考慮兼容問題的話,你可以直接拷貝這個庫的代碼片段,加上對參數邊界的處理就直接能用。
再有一點,這個庫之所以簡短,能夠讓你在30秒就理解,主要是能用規范提供的最新方法就用,不再很費勁的自己實現一套,全都調用了原生提供的方法,包括 ES6 的方法。每個方法都是獨立的,可獨立測試,獨立運行,和其他的方法互不牽扯,極大的降低了閱讀時找各種方法會被打斷思路的煩惱。
當然,如果你想閱讀 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個方法,你看簡單不簡單。
chunkchunk
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]]deepFlatten
深度平鋪一個數組。
使用遞歸。
使用 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]flatten
將數組展平到指定的深度。
使用遞歸,為每個深度級別 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]initialize2DArray
初始化一個給定行數和列數,以及值的二維數組。
使用 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]]union
返回兩個數組的并集,相同的元素只出現一次。
基于 a 和 b 創建一個 Set 對象,返回轉換后的數組。
const union = (a, b) => Array.from(new Set([...a, ...b]));
union([1, 2, 3], [4, 3, 2]); // [1,2,3,4]mapObject
使用一個函數將數組的值映射到對象,在鍵值對中,原始值作為鍵,映射值作為值。
使用一個匿名的內部函數作用域來聲明一個 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 }offset
將指定數量的元素移動到數組的末尾。
兩次使用 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]pull
改變原始數組,過濾掉指定的值。
使用 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" ]reducedFilter
根據條件過濾一個對象數組,同時過濾掉未指定的鍵。
使用 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"}]xProd
將兩個數組的每個元素兩兩進行組合,組合出所有的可能對存在數組中,返回一個存在所有可能性對的數組。
使用 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...。
如果對你有幫助,請關注【前端技能解鎖】:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106152.html
摘要:理解元編程和是屬于元編程范疇的,能介入的對象底層操作進行的過程中,并加以影響。元編程中的元的概念可以理解為程序本身。中,便是兩個可以用來進行元編程的特性。在之后,標準引入了,從而提供比較完善的元編程能力。 導讀 幾年前 ES6 剛出來的時候接觸過 元編程(Metaprogramming)的概念,不過當時還沒有深究。今天在應用和學習中不斷接觸到這概念,比如 mobx 5 中就用到了 Pr...
摘要:給定一個函數,返回一個閉包,該閉包將所有輸入收集到一個數組接受函數中。返回一個可變參數的閉包,在應用其他參數前,先把第一個以外的其他參數作為第一個參數。 showImg(https://segmentfault.com/img/remote/1460000018406951?w=1400&h=600); 本系列翻譯自開源項目 30-seconds-of-code這是一個非常優秀的系列,...
摘要:從現在開始,養成寫技術博客的習慣,或許可以在你的職業生涯發揮著不可忽略的作用。如果想了解更多優秀的前端資料,建議收藏下前端英文網站匯總這個網站,收錄了國外一些優質的博客及其視頻資料。 前言 寫文章是一個短期收益少,長期收益很大的一件事情,人們總是高估短期收益,低估長期收益。往往是很多人堅持不下來,特別是寫文章的初期,剛寫完文章沒有人閱讀會有一種挫敗感,影響了后期創作。 從某種意義上說,...
摘要:相當于的使用返回一個函數,返回一個調用原始函數的。你可以省略來使用窗口的默認值。第一個最左邊的函數可以接受一個或多個參數其余的功能必須是一元的。使用刪除任何空字符串。如果是位數的顏色代碼,則先轉換為位數字版本。轉顏色將的值轉換為顏色代碼。 原文基礎上增加了其它方法以及注釋等,進行了小幅度修改,便于閱讀注意箭頭函數有無{}會影響是否需要再return 原文地址 Adapter 適配器,以...
閱讀 3776·2021-08-30 09:47
閱讀 3703·2019-08-30 15:56
閱讀 680·2019-08-30 14:18
閱讀 702·2019-08-29 16:17
閱讀 2069·2019-08-29 11:07
閱讀 647·2019-08-26 13:53
閱讀 3449·2019-08-26 10:26
閱讀 2496·2019-08-23 18:30