摘要:相当于的使用返回一个函数,返回一个调用原始函数的。你可以省略来使用窗口的默认值。第一个最左边的函数可以接受一个或多个参数其余的功能必须是一元的。使用删除任何空字符串。如果是位数的颜色代码,则先转换为位数字版本。转颜色将的值转换为颜色代码。
原文基础上增加了其它方法以及注释等,进行了小幅度修改,便于阅读
注意箭头函数有无{}会影响是否需要再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"
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/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 的...
阅读 3383·2023-04-25 19:39
阅读 3784·2021-11-18 13:12
阅读 3618·2021-09-22 15:45
阅读 2409·2021-09-22 15:32
阅读 691·2021-09-04 16:40
阅读 3684·2019-08-30 14:11
阅读 1820·2019-08-30 13:46
阅读 1541·2019-08-29 15:43