摘要:相當于的使用返回一個函數,返回一個調用原始函數的。你可以省略來使用窗口的默認值。第一個最左邊的函數可以接受一個或多個參數其余的功能必須是一元的。使用刪除任何空字符串。如果是位數的顏色代碼,則先轉換為位數字版本。轉顏色將的值轉換為顏色代碼。
原文基礎上增加了其它方法以及注釋等,進行了小幅度修改,便于閱讀
注意箭頭函數有無{}會影響是否需要再return
原文地址
Adapter適配器,以下大多利用閉包返回函數和...操作符(剩余操作符/擴展操作符)
promise化(promisify)轉換異步函數以返回一個promise。相當于node的util.promisify
使用currying返回一個函數,返回一個調用原始函數的Promise。使用... rest運算符傳入所有參數。
const promisify = func => { return (...args) =>{ return new Promise((resolve, reject) => { return func(...args,(err,result) =>{ return err ? reject(err) : resolve(result) }) }) } } // const delay = promisify((d, cb) => setTimeout(cb, d)) // delay(2000).then(() => console.log("Hi!")) -> Promise resolves after 2s可變參數函數轉為數組參數函數
接受一個可變參數函數并返回一個閉包,該閉包接受一個參數數組映射到該函數的輸入。 使用閉包和展開運算符(...)將參數數組映射到函數的輸入。
const spreadOver = fn =>{ return argsArr =>{ return fn(...argsArr) } } /* const arrayMax = spreadOver(Math.max) arrayMax([1,2,3]) // -> 3 arrayMax([1,2,4]) // -> 4 */ // 簡單點可以 // Math.max(...[1,3,5])Array 數組最大值
Math.max()和擴展操作符...
const arrayMax = arr => Math.max(...arr)數組中去除假值
const compact = arr => arr.filter(Boolean)統計某項出現的次數
const countOccurrences = (arr, value) => { return arr.reduce((a,v) =>{ return v === value ? a + 1: a + 0 },0) }統計數組元素出現次數
const countedNames = (arr) => { return arr.reduce(function (accr, name) { if (name in accr) { accr[name]++; } else { accr[name] = 1; } return accr; }, {}); } // countedNames is: // { "Alice": 2, "Bob": 1, "Tiff": 1, "Bruce": 1 }深度扁平(map)
利用Array.concat()和...擴展操作符以及遞歸
const deepFlatten = arr => { return [].concat(...arr.map((v) =>{ return Array.isArray(v) ? deepFlatten(v) : v })) }找出兩個數組的不同項
利用set.has()和filter
const difference = (arr1, arr2) =>{ const s = new Set(arr2) return arr1.filter(x => !s.has(x)) }去重
const distinct = arr => [...new Set(arr)] const distinct = arr => [Array.from(new Set(arr))] const distinct = arr => { return arr.filter((i) => arr.indexOf(i) !== arr.lastIndexOf(i)) }過濾非唯一值
const filterNonUnique = arr =>{ return arr.filter((i) => arr.indexOf(i) === arr.lastIndexOf(i)) }扁平一層(reduce)
const flatten = arr => arr.reduce((a, v) => a.concat(v), [])扁平等級(depth)
根據depth等級來扁平,默認為1
const flattenDepth = (arr, depth = 1) =>{ if (depth ===1) { return arr.reduce((a, v) => a.concat(v), []) } return arr.reduce((a, v) => { return a.concat(Array.isArray(v) ? flattenDepth(v, depth-1) : v) }, []) }根據范圍填充
默認0到end
const initialWithRange = (end, start = 0) =>{ return Array.from({length:end + 1 - start}).map((v, i) =>{ return i + start }) } const initialWithRange = (end, start = 0) =>{ return new Array(end + 1 - start).fill().map((v, i) =>{ return i + start }) }兩個數組的交叉值
const intersection = (arr1, arr2) =>{ const s = new Set(arr2) return arr1.filter((x) => s.has(x)) }挑選(pick)
從對象中挑選與給定鍵對應的鍵值對。
const pick = (obj, arr) => arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); const pick = (obj, arr) => { return arr.reduce((acc, curr) => { curr in obj && (acc[curr] = obj[curr]) return acc }, {}) } // 本質,遍歷檢查一遍 const pick = (obj, arr) => { var temp = {} arr.forEach((item, index) => { if (item in obj){ temp[item] = obj[item] } }) return temp }隨機取數(sample)
同時也適用于字符串
const sample = arr =>{ return arr[Math.floor(Math.random()*arr.length)] }打亂(shuffle)
// 初級版 const shuffle = arr => arr.sort(() => Math.random() - 0.5) // random order function shuffle(array) { var random = array.map(Math.random) return array.sort(function(a, b) { return random[a] - random[b] }) } // Fisher–Yates(費歇爾洗牌算法) function shuffle(arr) { for (let i = arr.length; i > 0; i--){ //下面一行的";"不可去掉,否則會報錯 let j = Math.floor(Math.random() *i); [arr[i-1], arr[j]] = [arr[j], arr[i-1]] } return arr }相似值
const similarity = (arr1, arr2) =>{ return arr1.filter((item, i) => { return arr2.includes(item) }) } // similarity([1,2,3], [1,2,4]) -> [1,2]聯合(union)
const union = (arr1, arr2) => Array.from(new Set([...arr1, ...arr2])) // union([1,2,3], [4,3,2]) -> [1,2,3,4]排除
支持多參數傳入,利用...剩余操作符,不修改原數組
const without = (arr, ...args) =>{ return arr.filter((item) =>{ return !args.includes(item) }) } // without([2, 1, 2, 3], 1, 2) -> [3]降維/壓縮
...rest參數.根據原始數組中的位置進行分組,多個一維數組,按照原始位置進行合并為二維數組,空缺的用undefined占位
const zip = (...arrays) => { // 下面的...是擴展操作符,不然數組無法傳入到Math.max() const maxLength = Math.max(...arrays.map((item) => item.length)) return Array.from({length:maxLength}).map((_, i) =>{ return Array.from({length: arrays.length},(_, j) =>{ return arrays[j][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]]Browser 頁面底部是否可見
const bottomVisible = () => { return document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight) }偵測設備類型
移動設備/桌面設備
const detectDeviceType = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? "Mobile" : "Desktop"; } // detectDeviceType() -> "Desktop"元素是否在視窗可見
默認完全可見,懶加載的時候會用到這個原理
const elementIsVisibleInViewport = (el, partiallyVisible = false) => { const { top, left, bottom, right } = el.getBoundingClientRect(); return partiallyVisible ? ((top > 0 && top < window.innerHeight) || (bottom > 0 && bottom < window.innerHeight)) && ((left > 0 && left < window.innerWidth) || (right > 0 && right < window.innerWidth)) : top >= 0 && left >= 0 && bottom <= window.innerHeight && right <= window.innerWidth; };獲取url查詢參數
const getURLParameters = url => url.match(/([^?=&]+)(=([^&]*))/g).reduce( (a, v) => (a[v.slice(0, v.indexOf("="))] = v.slice(v.indexOf("=") + 1), a), {} );返回頁面頂部
const scrollToTop = () =>{ const distance = document.documentElement.scrollTop if(distance > 0){ window.requestAnimationFrame(scrollToTop) window.scrollTo(0, distance - distance/8) } }瀏覽器窗口大小(視窗)
一張網頁的全部面積,就是它的大小。通常情況下,網頁的大小由內容和CSS樣式表決定。
瀏覽器窗口的大小,則是指在瀏覽器窗口中看到的那部分網頁面積,又叫做viewport(視口)。
注意事項
必須在頁面加載完成后才能運行,否則document對象還沒生成,瀏覽器會報錯
clientWidth和clientHeight都是只讀屬性,不能對它們賦值。
window.innerWidth是包括右邊滾動條的寬度的
const getViewport = () =>{ return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight } }網頁大小
如果網頁內容能夠在瀏覽器窗口中全部顯示,不出現滾動條,那么網頁的clientWidth和scrollWidth應該相等。但是實際上,不同瀏覽器有不同的處理,這兩個值未必相等。所以,我們需要取它們之中較大的那個值
const getPageArea = () =>{ return { width: Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth), height: Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight) } }網頁元素絕對位置
指該元素的左上角相對于整張網頁左上角的坐標。這個絕對位置要通過計算才能得到。
不斷累加offsetParent的offsetTop和offsetLeft屬性
由于在表格和iframe中,offsetParent對象未必等于父容器,所以上面的函數對于表格和iframe中的元素不適用。
function getElementLeft(element){ var actualLeft = element.offsetLeft; var current = element.offsetParent; while (current !== null){ actualLeft += current.offsetLeft; current = current.offsetParent; } return actualLeft; } function getElementTop(element){ var actualTop = element.offsetTop; var current = element.offsetParent; while (current !== null){ actualTop += current.offsetTop; current = current.offsetParent; } return actualTop; }
利用getBoundingClientRect方法
此方法其中包含了left、right、top、bottom四個屬性,分別對應了該元素的左上角和右下角相對于瀏覽器窗口(viewport)左上角的距離.(其實也就是網頁元素的相對位置)
var X= this.getBoundingClientRect().left+document.documentElement.scrollLeft; var Y =this.getBoundingClientRect().top+document.documentElement.scrollTop;網頁元素相對位置
網頁元素的相對位置,指該元素左上角相對于瀏覽器窗口左上角的坐標。
有了絕對位置以后,獲得相對位置就很容易了,只要將絕對坐標減去頁面的滾動條滾動的距離就可以了 也就是減去document.documentElement.scrollLeft|scrollTop
//快捷方法 var X= this.getBoundingClientRect().left; var Y =this.getBoundingClientRect().top;滾動位置
返回當前頁面的滾動位置。請使用pageXOffset和pageYOffset, 如果已定義,否則使用scrollLeft和scrollTop。你可以省略el來使用窗口的默認值。pageXOffset是scrollY的別名(event.pageX是鼠標活動事件的屬性)
const getScrollPosition = (el = window) =>{ return ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft, y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop}); } // getScrollPosition() -> {x: 0, y: 200}Function 鏈式異步調用(chainAsync)
循環遍歷包含異步事件的函數數組,每次異步事件完成后再調用
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"); } ]) */組合
執行從右到左的函數功能組合
使用Array.reduce()來執行從右到左的函數組合。最后(最右邊的)函數可以接受一個或多個參數;其余的函數參數必須是一元的.
const compose = (...fns) => { return fns.reduce((f,g) => { //...args 剩余參數, args是數組,再轉換為函數參數 return (...args) => f(g(...args)) }) } /* const add5 = x => x + 5 const multiply = (x, y) => x * y const multiplyAndAdd5 = compose(add5, multiply) multiplyAndAdd5(5, 2) -> 15 */管道
執行從左到右的函數功能組合
使用Array.reduce()和spread運算符(...)來執行從左到右的函數組合。第一個(最左邊的)函數可以接受一個或多個參數;其余的功能必須是一元的。
const pipeFunctions = (...fns) => { return fns.reduce((f,g) => { //...args 剩余參數, args是數組,再轉換為函數參數 return (...args) => g(f(...args)) }) } /* */鏈式調用promise
使用Array.reduce()創建一個promise鏈,每個promise在解析后返回下一個promise
const promiseSeries = ps => { return ps.reduce((p, next) => { return p.then(next) }, Promise.resolve()) } // const delay = (d) => new Promise(r => setTimeout(r, d)) // runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete睡眠(sleep)
延遲異步函數的執行,延遲執行異步函數的一部分,通過把它放到睡眠狀態,返回一個Promise。
const sleep = ms => { return new Promise((resolve,reject) => { setTimeout(resolve, ms) }) } /* async function sleepyWork() { console.log("I"m going to sleep for 1 second."); await sleep(1000); console.log("I woke up after 1 second."); } */Math 數組總和
const arraySum = arr => { return arr.reduce((acc,curr) => { return acc + curr },0) }數組平均數
const arrayAverage = arr => { return arr.reduce((acc,curr) => { return acc + curr },0) / arr.length }數字數組化
const digitize = number =>{ return [...number.toString()] // return [...""+number] } // digitize(2334) -> [2, 3, 3, 4]階乘(factorial)
// 一個函數內處理的結果可以使用return 返回,這樣在調用函數的地方就可以用變量接收返回 結果 const factorial = n =>{ // 不return的話那就不會返回這個數值 默認返回的是undefined return n <= 1 ? 1 : n * factorial(n-1) } // factorial(6) -> 720斐波那契數列(fibonacci)
const fibonacci = n =>{ return Array(n).fill(0).reduce((acc, val, i) =>{ return acc.concat(i >1 ? acc[i -1] + acc[i -2] : i) }, []) } // fibonacci(5) -> [0,1,1,2,3]判斷素數
const isPrime = num =>{ for (var i = 2; i < num; i++) { if (num % i ===0){ return false } } return num >= 2; } // isPrime(11) -> true // isPrime(12) -> false // isPrime(1) -> false判斷回文
const palindrome = str =>{ const s = str.toLowerCase().replace(/[w_]/g, "") return s === s.split("").reverse().join("") } // palindrome("taco cat") -> true指定范圍隨機整數
const randomIntegerRange = (min, max) =>{ return Math.floor(Math.random()* (max - min +1)) + min } //randomIntegerRange (1, 10) -> 5四舍五入到指定小數位
const roundx = (n, decimals=0) => { return Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`) } // roundx(1.005, 2) -> 1.01 const roundx = (n, decimals=0) =>{ return n.toFixed(decimals) } // roundx(1.2, 3) -> "1.200"數組標準差
const standardDeviation = (arr, usePopulation = false) => { const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; return Math.sqrt( arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), []) .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1)) ); }; // standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)Media 語言轉文字(讀取文字)
了解有關Web Speech API的SpeechSynthesisUtterance接口的更多信息。
const speechSynthesis = message => { const msg = new SpeechSynthesisUtterance(message); msg.voice = window.speechSynthesis.getVoices()[0]; window.speechSynthesis.speak(msg); }; // speechSynthesis("Hello, World") -> plays the messageObject 給定數組創建對象
const objectFromPairs = arr => { return arr.reduce((acc, val) =>{ acc[val[0]] = val[1] return acc // return (acc[val[0]] = val[1], acc) },{}) } // objectFromPairs([["a",1],["b",2]]) -> {a: 1, b: 2}給定對象創建數組
const objectToPairs = obj =>{ return Object.keys(obj).map((key) =>{ return [key, obj[key]] }) } // objectToPairs({a: 1, b: 2}) -> [["a",1],["b",2]])對象深度選擇(select)
可以避免深度對象選擇不到時的報錯?
const select = (from, selector) =>{ return selector.split(".").reduce((prev,cur) =>{ return prev && prev[cur] },from) } // const obj = {selector: {to: {val: "val to select"}}}; // select(obj, "selector.to.val"); -> "val to select"對象組是否都含有給定的屬性
const truthCheckCollection = (collection, key) =>{ return collection.every((obj => { return obj[key] })) } // truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> trueString 首字母大寫(capitalize)
const capitalize = ([first, ...rest]) =>{ return first.toUpperCase() + rest.join("") } // capitalize("myName") -> "MyName"首字母大寫每個單詞
const capitalizeEveryWord = str =>{ // 匹配的單詞 return str.replace(/[a-z]/g, char =>{ return char.toUpperCase() }) }元音字符數
const countVowels = str => { // 匹配不到時返回null 所以用[]避免報錯 return (str.match(/[aeiou]/ig) || []).length }轉義字符串
轉義字符串以在正則表達式中使用。 使用replace()來轉義特殊字符。
const escapeRegExp = str =>{ return str.replace(/[.*+?^${}()|[]]/g, "$&") }轉換駝峰字符串
將駝峰形式的字符串轉換為指定字符分割的形式
const fromCamelCase = (str, separator = "_") =>{ return str.replace(/([a-zd])([A-Z])/g, "$1" + separator + "$2").replace(/([A-Z]+)([A-Z][a-zd]+)/g, "$1" + separator + "$2").toLowerCase() } // fromCamelCase("someDatabaseFieldName", " ") -> "some database field name" // fromCamelCase("someLabelThatNeedsToBeCamelized", "-") -> "some-label-that-needs-to-be-camelized" // fromCamelCase("someJavascriptProperty", "_") -> "some_javascript_property"轉換左右
const reverseString = str =>{ return str.split("").reverse().join("") } // reverseString("foobar") -> "raboof"按照字母排序
const sortCharactersInString = str =>{ return str.split("").sort((a, b) => { return a.localeCompare(b) }).join(""); } // sortCharactersInString("cabbage") -> "aabbceg"轉為駝峰
使用replace()去除下劃線,連字符和空格,并將單詞轉換為camelcase。
const toCamelCase = str =>{ return str.replace(/^([A-Z])|[s-_]+(w)/g, (match, p1, p2, offset) =>{ return p2 ? p2.toUpperCase() : p1.toLowerCase() }) } // toCamelCase("some_database_field_name") -> "someDatabaseFieldName" // toCamelCase("Some label that needs to be camelized") -> "someLabelThatNeedsToBeCamelized" // toCamelCase("some-javascript-property") -> "someJavascriptProperty" // toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> "someMixedStringWithSpacesUnderscoresAndHyphens"轉為單詞數組
使用String.split()與提供的模式(默認為非alpha作為正則表達式)來轉換為字符串數組。使用Array.filter()刪除任何空字符串。
const words = (str, pattrern = /[^a-zA-Z-]+/) =>{ return str.split(pattrern).filter(Boolean) } // ["I", "love", "javaScript", ""] // words("I love javaScript!!") -> ["I", "love", "javaScript"] // ["python", "javaScript", "coffee"] // words("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
## Utility
### 擴展Hex(16進制顏色)
將3位數的顏色代碼擴展為6位數的顏色代碼
const extendHex = shortHex => { return "#" + shortHex.slice(shortHex.startsWith("#") ? 1 : 0).split("").map( s => s+s).join("") }值的類型
const getType = v =>{ v === undefined ? "undefined" : v === null ? "null" : v.constructor.name.toLowerCase() } // getType(new Set([1,2,3])) -> "set"十六進制顏色轉rgb
如果提供了alpha值,則將顏色代碼轉換為rgb()或rgba()字符串。 使用&(和)運算符,按位右移運算符和掩碼位將具有RGB值的十六進制顏色代碼(帶或不帶前綴#)轉換為字符串。如果是3位數的顏色代碼,則先轉換為6位數字版本。如果一個alpha值和6位十六進制一起提供,則返回rgba()字符串。
const hexToRGB = hex => { let alpha = false, h = hex.slice(hex.startsWith("#") ? 1 : 0); if (h.length === 3) h = [...h].map(x => x + x).join(""); else if (h.length === 8) alpha = true; h = parseInt(h, 16); return "rgb" + (alpha ? "a" : "") + "(" + (h >>> (alpha ? 24 : 16)) + ", " + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ", " + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + (alpha ? `, ${(h & 0x000000ff)}` : "") + ")"; }; // hexToRGB("#27ae60ff") -> "rgba(39, 174, 96, 255)" // hexToRGB("27ae60") -> "rgb(39, 174, 96)" // hexToRGB("#fff") -> "rgb(255, 255, 255)"
### 隨機十六進制顏色
使用Math.random生成一個隨機的24位(6x4bits)十六進制數字。使用位移,然后使用toString(16)將其轉換為十六進制字符串。
const randomHexColorCode = () =>{ return "#"+(Math.random()*0xFFFFFF<<0).toString(16); } // randomHexColorCode() -> "#e34155" // randomHexColorCode() -> "#fd73a6" // randomHexColorCode() -> "#4144c6"rgb轉hex顏色
將RGB的值轉換為顏色代碼。 使用按位左移運算符(<<)和toString(16),然后padStart(6,“0”)將給定的RGB參數轉換為十六進制字符串以獲得6位十六進制值。
const RGBToHex = (r, g, b) => { return ((r << 16) + (g << 8) + b).toString(16).padStart(6, "0"); } // RGBToHex(255, 165, 1) -> "ffa501"UUID生成器
使用crypto API生成符合RFC4122版本4的UUID。
const UUIDGenerator = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); // UUIDGenerator() -> "7982fcfe-5721-4632-bede-6000885be57d"
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92276.html
摘要:詳情發布高性能實時應用程序框架帶來的最新增強功能,并通過集成,和簡化持續集成和持續部署。文中提出的反調試技巧包括檢測未知的執行環境檢測調試工具例如代碼完整性控制流完整性控制和反模擬。 01. Chrome65 的新功能 CSS Paint API 允許使用編程方式生成圖像;Server Timing API允許服務器將時間信息通過HTTP headers傳遞給瀏覽器; CSS disp...
摘要:詳情發布高性能實時應用程序框架帶來的最新增強功能,并通過集成,和簡化持續集成和持續部署。文中提出的反調試技巧包括檢測未知的執行環境檢測調試工具例如代碼完整性控制流完整性控制和反模擬。 01. Chrome65 的新功能 CSS Paint API 允許使用編程方式生成圖像;Server Timing API允許服務器將時間信息通過HTTP headers傳遞給瀏覽器; CSS disp...
摘要:詳情發布高性能實時應用程序框架帶來的最新增強功能,并通過集成,和簡化持續集成和持續部署。文中提出的反調試技巧包括檢測未知的執行環境檢測調試工具例如代碼完整性控制流完整性控制和反模擬。 01. Chrome65 的新功能 CSS Paint API 允許使用編程方式生成圖像;Server Timing API允許服務器將時間信息通過HTTP headers傳遞給瀏覽器; CSS disp...
摘要:所以,我們可以將理解為計時結束是執行任務的必要條件,但是不是任務是否執行的決定性因素。的意思是,必須超過毫秒后,才允許執行。 先來回答一下下面這個問題:對于 setTimeout(function() { console.log(timeout) }, 1000) 這一行代碼,你從哪里可以找到 setTimeout 的源代碼(同樣的問題還會是你從哪里可以看到 setInterval 的...
閱讀 3459·2023-04-25 19:39
閱讀 3810·2021-11-18 13:12
閱讀 3637·2021-09-22 15:45
閱讀 2437·2021-09-22 15:32
閱讀 722·2021-09-04 16:40
閱讀 3731·2019-08-30 14:11
閱讀 1890·2019-08-30 13:46
閱讀 1567·2019-08-29 15:43