Util.js _(持續更新中...)_ 項目地址 : https://github.com/dragonir/Util.js 項目描述 Util.js 是對常用函數的封裝,方便在實際項目中使用,主要內容包含:數組類、瀏覽器類、日期類、函數類、數學類、媒體類、節點類、對象類、字元串類、類型檢測類、正 ...
Util.js (持續更新中...)
項目描述
Util.js 是對常用函數的封裝,方便在實際項目中使用,主要內容包含:數組類、瀏覽器類、日期類、函數類、數學類、媒體類、節點類、對象類、字元串類、類型檢測類、正則表達式類等內容。
使用方法
1. 引入Bable transpiler以保證支持ES6
<script type="javascript/text" src="./browser.js"></script>
或引入壓縮版
<script type="javascript/text" src="./browser.min.js"></script>
2. 引入工具函數文件Util.js
<script type="javascript/text" src="./Util.js"></script>
或引入壓縮版
<script type="javascript/text" src="./Util.min.js"></script>
3. 使用舉例
Example 1: 通過調用 isArray() 方法來判斷數值是否為數組
var arr = [];
var obj = {};
console.log(Util.isArray(arr)); // true
console.log(Util.isArray(obj)); // false
Example 2: 通過調用 extendHex() 方法將3位色值轉換為6位色值
console.log(Util.extendHex("#03f")); // #0033ff
console.log(Util.extendHex("05a")); // #0055aa
console.log(Util.extendHex("#03c03c")); // #03c03c
項目目錄
文件名 | 描述 |
---|---|
Util.js | 工具函數主文件 |
Util.min.js | 工具函數壓縮版 |
RegExp.js | 正則表達式封裝 |
RegExp.min.js | 正則表達式封裝壓縮版 |
browser.js | ES6向後相容 |
browser.min.js | ES6向後相容 |
string-utils.js | 字元串工具函數(待整合) |
00. 常用正則表達式示例-RegExp.html | 正則表達式測試演示 |
01. 常用工具函數示例-Util-數組類.html | 數組類測試演示 |
02. 常用工具函數示例-Util-瀏覽器類.html | 瀏覽器類測試演示 |
03. 常用工具函數示例-Util-日期類.html | 日期類測試演示 |
04. 常用工具函數示例-Util-函數類.html | 函數類測試演示 |
05. 常用工具函數示例-Util-數學類.html | 數學類測試演示 |
06. 常用工具函數示例-Util-媒體類.html | 媒體類測試演示 |
07. 常用工具函數示例-Util-節點類.html | 設為首頁 |
08. 常用工具函數示例-Util-對象類.html | 對象類測試演示 |
09. 常用工具函數示例-Util-字元串.html | 字元串測試演示 |
10. 常用工具函數示例-Util-其他實用函數.html | 其他實用函數測試演示 |
11. 常用工具函數示例-Util-類型檢測.html | 類型檢測 |
README.MD | 項目描述文件 |
logo.png | 項目圖標 |
參考資料
感謝原作者分享了大量有用的Javascript片段,我在其基礎上將其封裝為一個文件方便使用。
內容目錄
以下是項目具體內容以及詳細註釋,可通過查詢找到自己需要的函數。
數組類
arrayMax
arrayMin
chunk
compact
countOccurrences
deepFlatten
difference
distinctValuesOfArray
dropElements
everyNth
filterNonUnique
flatten
flattenDepth
groupBy
head
initial
initializeArrayWithRange
initializeArrayWithValues
intersection
last
mapObject
nthElement
pick
pull
remove
sample
shuffle
similarity
symmetricDifference
tail
take
takeRight
union
without
zip
瀏覽器
bottomVisible
currentURL
elementIsVisibleInViewport
getScrollPosition
getURLParameters
redirect
scrollToTop
時間
函數
數學
arrayAverage
arraySum
collatz
digitize
distance
factorial
fibonacci
gcd
hammingDistance
isDivisible
isEven
lcm
median
palindrome
percentile
powerset
randomIntegerInRange
randomNumberInRange
round
standardDeviation
媒體
節點
對象
字元串
anagrams
capitalize
capitalizeEveryWord
escapeRegExp
fromCamelCase
reverseString
sortCharactersInString
toCamelCase
truncateString
工具
coalesce
coalesceFactory
extendHex
getType
hexToRGB
isArray
isBoolean
isFunction
isNumber
isString
isSymbol
RGBToHex
timeTaken
toOrdinalSuffix
UUIDGenerator
validateEmail
validateNumber
數組
arrayMax
返回數組中的最大值。
將Math.max()
與擴展運算符 (...
) 結合使用以獲取數組中的最大值。
const arrayMax = arr => Math.max(...arr);
// arrayMax([10, 1, 5]) -> 10
arrayMin
返回數組中的最小值。
將Math.min()
與擴展運算符 (...
) 結合使用以獲取數組中的最小值。
const arrayMin = arr => Math.min(...arr);
// arrayMin([10, 1, 5]) -> 1
chunk
將數組塊劃分為指定大小的較小數組。
使用Array.from()
創建新的數組, 這符合將生成的區塊數。使用Array.slice()
將新數組的每個元素映射到size
長度的區塊。如果原始數組不能均勻拆分, 則最終的塊將包含剩餘的元素。
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]]
compact
從數組中移除 falsey 值。
使用Array.filter()
篩選出 falsey 值 (false
、null
、0
、""
、undefined
和NaN
).
const compact = (arr) => arr.filter(Boolean);
// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
countOccurrences
計算數組中值的出現次數。
使用Array.reduce()
在每次遇到數組中的特定值時遞增計數器。
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
// countOccurrences([1,1,2,1,2,3], 1) -> 3
deepFlatten
深拼合數組。
使用遞歸。使用Array.concat()
與空數組 ([]
) 和跨頁運算符 (...
) 來拼合數組。遞歸拼合作為數組的每個元素。
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
difference
返回兩個數組之間的差異。
從b
創建Set
, 然後使用Array.filter()
on 只保留a
b
中不包含的值.
const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
// difference([1,2,3], [1,2,4]) -> [3]
distinctValuesOfArray
返回數組的所有不同值。
使用 ES6 Set
和...rest
運算符放棄所有重覆的值。
const distinctValuesOfArray = arr => [...new Set(arr)];
// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
dropElements
移除數組中的元素, 直到傳遞的函數返回true
。返回數組中的其餘元素。
在數組中迴圈, 使用Array.shift()
將數組的第一個元素除去, 直到函數的返回值為true
。返回其餘元素。
const dropElements = (arr, func) => {
while (arr.length > 0 && !func(arr[0])) arr.shift();
return arr;
};
// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
everyNth
返回數組中的每個第 n 個元素。
使用Array.filter()
創建一個包含給定數組的每個第 n 個元素的新數組。
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
filterNonUnique
篩選出數組中的非唯一值。
對於只包含唯一值的數組, 請使用Array.filter()
。
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
flatten
拼合數組。
使用Array.reduce()
獲取數組中的所有元素和concat()
以拼合它們。
const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
// flatten([1,[2],3,4]) -> [1,2,3,4]
flattenDepth
將數組向上拼合到指定深度。
使用遞歸, 遞減depth
, 每層深度為1。使用Array.reduce()
和Array.concat()
來合併元素或數組。基本情況下, 對於等於1
的depth
停止遞歸。省略第二個元素,depth
僅拼合到1
的深度 (單個拼合)。
const flattenDepth = (arr, depth = 1) =>
depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
: arr.reduce((a, v) => a.concat(v), []);
// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
groupby
根據給定函數對數組元素進行分組。
使用Array.map()
將數組的值映射到函數或屬性名。使用Array.reduce()
創建一個對象, 其中的鍵是從映射的結果生成的。
const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func])
.reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {});
// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
head
返回列表的頭。
使用arr[0]
可返回傳遞的數組的第一個元素。
const head = arr => arr[0];
// head([1,2,3]) -> 1
initial
返回除最後一個數組之外的所有元素。
使用 "arr.slice(0,-1)
" 返回數組的最後一個元素。
const initial = arr => arr.slice(0, -1);
// initial([1,2,3]) -> [1,2]
initializeArrayWithRange
初始化包含指定範圍內的數字的數組。
使用Array(end-start)
創建所需長度的數組Array.map()
以填充區域中所需的值。可以省略start
以使用預設值0
.
const initializeArrayWithRange = (end, start = 0) =>
Array.from({ length: end - start }).map((v, i) => i + start);
// initializeArrayWithRange(5) -> [0,1,2,3,4]
initializeArrayWithValues
初始化並填充具有指定值的數組。
使用Array(n)
創建所需長度的數組,fill(v)
以填充所需的值。可以省略value
以使用預設值0
.
const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
intersection
返回兩個數組中存在的元素的列表。
從b
創建Set
, 然後使用Array.filter()
on a
只保留b
中包含的值.
const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
// intersection([1,2,3], [4,3,2]) -> [2,3]
last
返回數組中的最後一個元素。
使用arr.length - 1
可計算給定數組的最後一個元素的索引並返回它。
const last = arr => arr[arr.length - 1];
// last([1,2,3]) -> 3
mapObject
使用函數將數組的值映射到對象, 其中鍵值對由原始值作為鍵和映射值組成。
使用匿名內部函數範圍來聲明未定義的記憶體空間, 使用閉包來存儲返回值。使用新的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 }
*/
nthElement
返回數組的第 n 個元素。
使用Array.slice()
可獲取包含第 n 個元素的數組。如果索引超出界限, 則返回[]
。省略第二個參數n
, 以獲取數組的第一個元素。
const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
// nthElement(['a','b','c'],1) -> 'b'
// nthElement(['a','b','b'],-3) -> 'a'
pick
從對象中選取對應於給定鍵的鍵值對。
使用Array.reduce()
將篩選/選取的密鑰轉換回具有相應鍵值對的對象 (如果在 obj 中存在該鍵)。
const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
pull
對原始數組進行變異, 以篩選出指定的值。
使用Array.filter()
和Array.includes()
來拉出不需要的值。使用Array.length = 0
可將傳入的數組中的長度重置為零, 並將其設置為Array.push()
, 以便僅使用所提取的值填充它。
const pull = (arr, ...args) => {
let pulled = arr.filter((v, i) => !args.includes(v));
arr.length = 0; pulled.forEach(v => arr.push(v));
};
// let myArray = ['a', 'b', 'c', 'a', 'b', 'c'];
// pull(myArray, 'a', 'c');
// console.log(myArray) -> [ 'b', 'b' ]
remove
從數組中移除給定函數返回false
的元素.
使用Array.filter()
查找返回 truthy 值的數組元素和Array.reduce()
以使用Array.splice()
刪除元素。使用三參數 (func
value, index, array
調用函數).
const remove = (arr, func) =>
Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
arr.splice(arr.indexOf(val), 1); return acc.concat(val);
}, [])
: [];
// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
sample
返回數組中的隨機元素。
使用Math.random()
生成一個隨機數, 將它與length
相乘, 並使用數學將其舍入到最接近的整數Math.floor()
。此方法也適用於字元串。
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
// sample([3, 7, 9, 11]) -> 9
shuffle
隨機數組值的順序。
使用Array.sort()
可在比較器中使用Math.random()
重新排序元素。
const shuffle = arr => arr.sort(() => Math.random() - 0.5);
// shuffle([1,2,3]) -> [2,3,1]
similarity
返回兩個數組中都顯示的元素的數組。
使用filter()
可刪除不屬於values
的值, 使用includes()
確定.
const similarity = (arr, values) => arr.filter(v => values.includes(v));
// similarity([1,2,3], [1,2,4]) -> [1,2]
symmetricDifference
返回兩個數組之間的對稱差。
從每個數組創建一個Set
, 然後對它們中的每一個都使用Array.filter()
, 以便只保留其他值中不包含的數值。
const symmetricDifference = (a, b) => {
const sA = new Set(a), sB = new Set(b);
return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
}
// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
tail
返回數組中的所有元素, 除第一個。
如果數組的length
大於1
, 則返回arr.slice(1)
, 否則返回整個數組。
const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
// tail([1,2,3]) -> [2,3]
// tail([1]) -> [1]
take
返回一個數組, 其中 n 個元素從開始處移除。
使用Array.slice()
創建數組的切片, 其中包含從開始處取出的n
元素。
const take = (arr, n = 1) => arr.slice(0, n);
// take([1, 2, 3], 5) -> [1, 2, 3]
// take([1, 2, 3], 0) -> []
takeRight
返回一個數組, 其中 n 個元素從末尾移除。
使用Array.slice()
創建數組的切片, 其中包含從末尾取出的n
元素。
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
// takeRight([1, 2, 3]) -> [3]
union
返回在兩個數組中的任意一個中存在的每個元素。
創建一個Set
, 其中包含a
和b
的所有值, 並將其轉換為數組。
const union = (a, b) => Array.from(new Set([...a, ...b]));
// union([1,2,3], [4,3,2]) -> [1,2,3,4]
without
篩選出數組中具有指定值之一的元素。
使用Array.filter()
創建不包括的數組 (使用!Array.includes()
) 所有給定值。
const without = (arr, ...args) => arr.filter(v => !args.includes(v));
// without([2, 1, 2, 3], 1, 2) -> [3]
zip
創建基於原始數組中的位置分組的元素數組。
使用Math.max.apply()
獲取參數中最長的數組。創建一個以該長度為返回值的數組, 並使用 map 函數創建一個分組元素的數組Array.from()
如果參數數組的長度不同, 則在未找到任何值的情況下使用undefined
。
const zip = (...arrays) => {
const maxLength = Math.max(...arrays.map(x => x.length));
return Array.from({length: maxLength}).map((_, i) => {
return Array.from({length: arrays.length}, (_, k) => arrays[k][i]);
})
}
//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
瀏覽器
bottomVisible
如果頁的底部可見, 則返回true
, 否則為false
。
使用scrollY
、scrollHeight
和clientHeight
來確定頁面底部是否可見。
const bottomVisible = () =>
document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight;
// bottomVisible() -> true
currentURL
返回當前 URL。
使用window.location.href
獲取當前 URL。
const currentURL = () => window.location.href;
// currentUrl() -> 'https://google.com'
elementIsVisibleInViewport
如果指定的元素在視區中可見, 則返回true
, 否則為false
。
使用Element.getBoundingClientRect()
和window.inner(Width|Height)
值以確定給定元素在視區中是否可見。省略第二個參數以確定該元素是否完全可見, 或指定true
以確定它是否部分可見。
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
const { top, left, bottom, right } = el.getBoundingClientRect();
return partiallyVisible
? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
: top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
// e.g. 100x100 viewport and a 10x10px element at position {top: -1, left: 0, bottom: 9, right: 10}
// elementIsVisibleInViewport(el) -> false (not fully visible)
// elementIsVisibleInViewport(el, true) -> true (partially visible)
getScrollPosition
返回當前頁的滾動位置。
如果已定義, 則使用pageXOffset
和pageYOffset
, 否則scrollLeft
和scrollTop
。可以省略el
以使用window
的預設值.
const getScrollPosition = (el = window) =>
({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop});
// getScrollPosition() -> {x: 0, y: 200}
getURLParameters
返回一個包含當前 URL 參數的對象。
使用match()
與適當的正則表達式來獲取所有鍵值對,Array.reduce()
可將它們映射併合併到單個對象中。將location.search
作為要應用於當前url
的參數傳遞.
const getURLParameters = url =>
url.match(/([^?=&]+)(=([^&]*))/g).reduce(
(a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
);
// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
redirect
重定向到指定的 URL。
使用window.location.href
或window.location.replace()
重定向到url
。傳遞第二個參數以模擬鏈接單擊 (true
-預設值) 或 HTTP 重定向 (false
).
const redirect = (url, asLink = true) =>
asLink ? window.location.href = url : window.location.replace(url);
// redirect('https://google.com')
scrollToTop
平滑滾動到頁面頂部。
使用document.documentElement.scrollTop
或document.body.scrollTop
從頂部獲取距離。從頂部的距離的一小部分滾動。使用window.requestAnimationFrame()
對滾動進行動畫處理。
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
// scrollToTop()
日期
getDaysDiffBetweenDates
返回兩個日期之間的差異 (以天為值)。
計算Date
對象之間的差異 (以天為)。
const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
JSONToDate
將 JSON 對象轉換為日期。
使用Date()
, 將 JSON 格式的日期轉換為可讀格式 (dd/mm/yyyy
日)).
const JSONToDate = arr => {
const dt = new Date(parseInt(arr.toString().substr(6)));
return `${ dt.getDate() }/${ dt.getMonth() + 1 }/${ dt.getFullYear() }`
};
// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
toEnglishDate
將日期從美國格式轉換為英文格式。
使用Date.toISOString()
、split('T')
和replace()
將日期從美式格式轉換為英文格式。如果傳遞的時間不能轉換為日期, 則拋出錯誤。
const toEnglishDate = (time) =>
{try{return new Date(time).toISOString().split('T')[0].replace(/-/g, '/')}catch(e){return}};
// toEnglishDate('09/21/2010') -> '21/09/2010'
函數類
chainAsync
鏈非同步函數。
迴圈遍歷包含非同步事件的函數數組, 當每個非同步事件完成時調用next
。
const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
/*
chainAsync([
next => { console.log('0 seconds'); setTimeout(next, 1000); },
next => { console.log('1 second'); setTimeout(next, 1000); },
next => { console.log('2 seconds'); }
])
*/
compose
執行從右向左的函數組合。
使用Array.reduce()
執行從右向左的函數組合。最後一個 (最右邊) 的函數可以接受一個或多個參數;其餘的函數必須是一元的。
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
/*
const add5 = x => x + 5
const multiply = (x, y) => x * y
const multiplyAndAdd5 = compose(add5, multiply)
multiplyAndAdd5(5, 2) -> 15
*/
curry
Curries a function.
使用遞歸。如果提供的參數 (變數) 的數量足夠, 請調用傳遞的函數args
f
。否則, 返回需要其餘參數的擴充函數f
。如果你想咖喱一個函數, 接受可變數目的參數 (如Math.min()
), 可以選擇將參數的個數傳遞到第二個參數arity
(可變函數).
const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length
? fn(...args)
: curry.bind(null, fn, arity, ...args);
// curry(Math.pow)(2)(10) -> 1024