236.扁平化数组
方案一:递归 + ...
| function flatten(arr, depth = -1) { |
| if (depth === -1) { |
| return [].concat( |
| ...arr.map((v) => (Array.isArray(v) ? this.flatten(v) : v)) |
| ); |
| } |
| if (depth === 1) { |
| return arr.reduce((a, v) => a.concat(v), []); |
| } |
| return arr.reduce( |
| (a, v) => a.concat(Array.isArray(v) ? this.flatten(v, depth - 1) : v), |
| [] |
| ); |
| } |
| flatten([1,[2,[3]]]) |
方案二:es6 原生 flat
| function flatten(arr, depth = Infinity) { |
| return arr.flat(depth) |
| } |
| flatten([1,[2,[3]]]) |
对比两个数组并且返回其中不同的元素
方案一:filter + includes
他原文有问题,以下方法的 4,5 没有返回
| function diffrence(arrA, arrB) { |
| return arrA.filter((v) => !arrB.includes(v)); |
| } |
| diffrence([1,2,3], [3,4,5,2]) |
需要再操作一遍
| function diffrence(arrA, arrB) { |
| return arrA.filter((v) => !arrB.includes(v)) |
| .concat(arrB.filter((v) => !arrA.includes(v))); |
| } |
| diffrence([1,2,3], [3,4,5,2]) |
方案二:hash + 遍历
算是方案1的变种吧,优化了 includes 的性能。
237.返回两个数组中相同的元素
方案一:filter + includes
| function intersection(arr1, arr2) { |
| return arr2.filter((v) => arr1.includes(v)); |
| } |
| intersection([1,2,3], [3,4,5,2]) |
方案二:同理变种用 hash
| function intersection(arr1, arr2) { |
| var set = new Set(arr2) |
| return arr1.filter((v) => set.has(v)); |
| } |
| intersection([1,2,3], [3,4,5,2]) |
238.从右删除 n 个元素
方案一:slice
| function dropRight(arr, n = 0) { |
| return n < arr.length ? arr.slice(0, arr.length - n) : []; |
| } |
| dropRight([1,2,3,4,5], 2) |
方案二: splice
| function dropRight(arr, n = 0) { |
| return arr.splice(0, arr.length - n) |
| } |
| dropRight([1,2,3,4,5], 2) |
方案三: slice 另一种
| function dropRight(arr, n = 0) { |
| return arr.slice(0, -n) |
| } |
| dropRight([1,2,3,4,5], 2) |
方案四: 修改 length
| function dropRight(arr, n = 0) { |
| arr.length = Math.max(arr.length - n, 0) |
| return arr |
| } |
| dropRight([1,2,3,4,5], 2) |
239.截取第一个符合条件的元素及其以后的元素
方案一:slice + 循环
| function dropElements(arr, fn) { |
| while (arr.length && !fn(arr[0])) arr = arr.slice(1); |
| return arr; |
| } |
| dropElements([1,2,3,4,5,1,2,3], (v) => v == 2) |
方案二:findIndex + slice
| function dropElements(arr, fn) { |
| return arr.slice(Math.max(arr.findIndex(fn), 0)); |
| } |
| dropElements([1,2,3,4,5,1,2,3], (v) => v === 3) |
方案三:splice + 循环
| function dropElements(arr, fn) { |
| while (arr.length && !fn(arr[0])) arr.splice(0,1); |
| return arr; |
| } |
| dropElements([1,2,3,4,5,1,2,3], (v) => v == 2) |
240.返回数组中下标间隔 nth 的元素
方案一:filter
| function everyNth(arr, nth) { |
| return arr.filter((v, i) => i % nth === nth - 1); |
| } |
| everyNth([1,2,3,4,5,6,7,8], 2) |
方案二:方案一修改判断条件
| function everyNth(arr, nth) { |
| return arr.filter((v, i) => (i+1) % nth === 0); |
| } |
| everyNth([1,2,3,4,5,6,7,8], 2) |
241.返回数组中第 n 个元素(支持负数)
方案一:slice
| function nthElement(arr, n = 0) { |
| return (n >= 0 ? arr.slice(n, n + 1) : arr.slice(n))[0]; |
| } |
| nthElement([1,2,3,4,5], 0) |
| nthElement([1,2,3,4,5], -1) |
方案二:三目运算符
| function nthElement(arr, n = 0) { |
| return (n >= 0 ? arr[0] : arr[arr.length + n]) |
| } |
| nthElement([1,2,3,4,5], 0) |
| nthElement([1,2,3,4,5], -1) |
242.返回数组头元素
方案一:
| function head(arr) { |
| return arr[0]; |
| } |
| head([1,2,3,4]) |
方案二:
| function head(arr) { |
| return arr.slice(0,1)[0]; |
| } |
| head([1,2,3,4]) |
243.返回数组末尾元素
方案一:
| function last(arr) { |
| return arr[arr.length - 1]; |
| } |
方案二:
| function last(arr) { |
| return arr.slice(-1)[0]; |
| } |
| last([1,2,3,4,5]) |
245.数组乱排
方案一:洗牌算法
| function shuffle(arr) { |
| let array = arr; |
| let index = array.length; |
| |
| while (index) { |
| index -= 1; |
| let randomInedx = Math.floor(Math.random() * index); |
| let middleware = array[index]; |
| array[index] = array[randomInedx]; |
| array[randomInedx] = middleware; |
| } |
| |
| return array; |
| } |
| shuffle([1,2,3,4,5]) |
方案二:sort + random
| function shuffle(arr) { |
| return arr.sort((n,m)=>Math.random() - .5) |
| } |
| shuffle([1,2,3,4,5]) |
246.伪数组转换为数组
方案一:Array.from
Array.from({length: 2})
方案二:prototype.slice
Array.prototype.slice.call({length: 2,1:1})
方案三:prototype.splice
Array.prototype.splice.call({length: 2,1:1},0)
浏览器对象 BOM
195.判读浏览器是否支持 CSS 属性
| |
| |
| |
| |
| |
| function validateCssKey(key) { |
| const jsKey = toCamelCase(key); |
| if (jsKey in document.documentElement.style) { |
| return key; |
| } |
| let validKey = ""; |
| |
| |
| const prefixMap = { |
| Webkit: "-webkit-", |
| Moz: "-moz-", |
| ms: "-ms-", |
| O: "-o-", |
| }; |
| for (const jsPrefix in prefixMap) { |
| const styleKey = toCamelCase(`${jsPrefix}-${jsKey}`); |
| if (styleKey in document.documentElement.style) { |
| validKey = prefixMap[jsPrefix] + key; |
| break; |
| } |
| } |
| return validKey; |
| } |
| |
| |
| |
| |
| function toCamelCase(value) { |
| return value.replace(/-(\w)/g, (matched, letter) => { |
| return letter.toUpperCase(); |
| }); |
| } |
| |
| |
| |
| |
| |
| |
| |
| function valiateCssValue(key, value) { |
| const prefix = ["-o-", "-ms-", "-moz-", "-webkit-", ""]; |
| const prefixValue = prefix.map((item) => { |
| return item + value; |
| }); |
| const element = document.createElement("div"); |
| const eleStyle = element.style; |
| |
| |
| prefixValue.forEach((item) => { |
| eleStyle[key] = item; |
| }); |
| return eleStyle[key]; |
| } |
| |
| |
| |
| |
| |
| |
| |
| function valiateCssValue(key, value) { |
| var prefix = ["-o-", "-ms-", "-moz-", "-webkit-", ""]; |
| var prefixValue = []; |
| for (var i = 0; i < prefix.length; i++) { |
| prefixValue.push(prefix[i] + value); |
| } |
| var element = document.createElement("div"); |
| var eleStyle = element.style; |
| for (var j = 0; j < prefixValue.length; j++) { |
| eleStyle[key] = prefixValue[j]; |
| } |
| return eleStyle[key]; |
| } |
| |
| function validCss(key, value) { |
| const validCss = validateCssKey(key); |
| if (validCss) { |
| return validCss; |
| } |
| return valiateCssValue(key, value); |
| } |
segmentfault.com/a/11... 它里面有 forEach。
247.返回当前网页地址
方案一:location
| function currentURL() { |
| return window.location.href; |
| } |
| currentURL() |
方案二:a 标签
| function currentURL() { |
| var el = document.createElement('a') |
| el.href = '' |
| return el.href |
| } |
| currentURL() |
获取滚动条位置
| function getScrollPosition(el = window) { |
| return { |
| x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, |
| y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop, |
| }; |
| } |
248.获取 url 中的参数
方案一:正则 + reduce
| function getURLParameters(url) { |
| return url |
| .match(/([^?=&]+)(=([^&]*))/g) |
| .reduce( |
| (a, v) => ( |
| (a[v.slice(0, v.indexOf("="))] = v.slice(v.indexOf("=") + 1)), a |
| ), |
| {} |
| ); |
| } |
| getURLParameters(location.href) |
方案二:split + reduce
| function getURLParameters(url) { |
| return url |
| .split('?') |
| .slice(1) |
| .join() |
| .split('&') |
| .map(v=>v.split('=')) |
| .reduce((s,n)=>{s[n[0]] = n[1];return s},{}) |
| } |
| getURLParameters(location.href) |
| |
方案三: URLSearchParams
249.页面跳转,是否记录在 history 中
方案一:
| function redirect(url, asLink = true) { |
| asLink ? (window.location.href = url) : window.location.replace(url); |
| } |
方案二:
| function redirect(url, asLink = true) { |
| asLink ? window.location.assign(url) : window.location.replace(url); |
| } |
250.滚动条回到顶部动画
方案一: c - c / 8
c 没有定义
| function scrollToTop() { |
| const scrollTop = |
| document.documentElement.scrollTop || document.body.scrollTop; |
| if (scrollTop > 0) { |
| window.requestAnimationFrame(scrollToTop); |
| window.scrollTo(0, c - c / 8); |
| } else { |
| window.cancelAnimationFrame(scrollToTop); |
| } |
| } |
| scrollToTop() |
修正之后
| function scrollToTop() { |
| const scrollTop = |
| document.documentElement.scrollTop || document.body.scrollTop; |
| if (scrollTop > 0) { |
| window.requestAnimationFrame(scrollToTop); |
| window.scrollTo(0, scrollTop - scrollTop / 8); |
| } else { |
| window.cancelAnimationFrame(scrollToTop); |
| } |
| } |
| scrollToTop() |
251.复制文本
方案一:
| function copy(str) { |
| const el = document.createElement("textarea"); |
| el.value = str; |
| el.setAttribute("readonly", ""); |
| el.style.position = "absolute"; |
| el.style.left = "-9999px"; |
| el.style.top = "-9999px"; |
| document.body.appendChild(el); |
| const selected = |
| document.getSelection().rangeCount > 0 |
| ? document.getSelection().getRangeAt(0) |
| : false; |
| el.select(); |
| document.execCommand("copy"); |
| document.body.removeChild(el); |
| if (selected) { |
| document.getSelection().removeAllRanges(); |
| document.getSelection().addRange(selected); |
| } |
| } |
方案二:cliboard.js
252.检测设备类型
方案一: ua
| function detectDeviceType() { |
| return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( |
| navigator.userAgent |
| ) |
| ? "Mobile" |
| : "Desktop"; |
| } |
| detectDeviceType() |
方案二:事件属性
| function detectDeviceType() { |
| return ("ontouchstart" in window || navigator.msMaxTouchPoints) |
| ? "Mobile" |
| : "Desktop"; |
| } |
| detectDeviceType() |
253.Cookie
增
| function setCookie(key, value, expiredays) { |
| var exdate = new Date(); |
| exdate.setDate(exdate.getDate() + expiredays); |
| document.cookie = |
| key + |
| "=" + |
| escape(value) + |
| (expiredays == null ? "" : ";expires=" + exdate.toGMTString()); |
| } |
删
| function delCookie(name) { |
| var exp = new Date(); |
| exp.setTime(exp.getTime() - 1); |
| var cval = getCookie(name); |
| if (cval != null) { |
| document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); |
| } |
| } |
查
| function getCookie(name) { |
| var arr, |
| reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); |
| if ((arr = document.cookie.match(reg))) { |
| return arr[2]; |
| } else { |
| return null; |
| } |
| } |
清空
有时候我们想清空,但是又无法获取到所有的cookie。 这个时候我们可以了利用写满,然后再清空的办法。
日期 Date
254.时间戳转换为时间
- 默认为当前时间转换结果
- isMs 为时间戳是否为毫秒
| function timestampToTime(timestamp = Date.parse(new Date()), isMs = true) { |
| const date = new Date(timestamp * (isMs ? 1 : 1000)); |
| return `${date.getFullYear()}-${ |
| date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1 |
| }-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`; |
| } |
- 补位可以改成 padStart
- 补位还可以改成 slice
如果做海外的话,还会有时区问题,一般我用moment解决。如果想看原生的
获取当前时间戳
基于上一个想到的问题
方案一:Date.parse(new Date())
方案二:Date.now()
方案三:+new Date()
文档对象 DOM
255固定滚动条
| |
| |
| |
| |
| let scrollTop = 0; |
| |
| function preventScroll() { |
| |
| scrollTop = window.scrollY; |
| |
| |
| document.body.style["overflow-y"] = "hidden"; |
| document.body.style.position = "fixed"; |
| document.body.style.width = "100%"; |
| document.body.style.top = -scrollTop + "px"; |
| |
| } |
| |
| function recoverScroll() { |
| document.body.style["overflow-y"] = "auto"; |
| document.body.style.position = "static"; |
| |
| |
| window.scrollTo(0, scrollTop); |
| } |
256 判断当前位置是否为页面底部
| function bottomVisible() { |
| return ( |
| document.documentElement.clientHeight + window.scrollY >= |
| (document.documentElement.scrollHeight || |
| document.documentElement.clientHeight) |
| ); |
| } |
257判断元素是否在可视范围内
- partiallyVisible 为是否为完全可见
| function 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; |
| } |
258.获取元素 css 样式
| function getStyle(el, ruleName) { |
| return getComputedStyle(el, null).getPropertyValue(ruleName); |
| } |
259.进入全屏
| function launchFullscreen(element) { |
| if (element.requestFullscreen) { |
| element.requestFullscreen(); |
| } else if (element.mozRequestFullScreen) { |
| element.mozRequestFullScreen(); |
| } else if (element.msRequestFullscreen) { |
| element.msRequestFullscreen(); |
| } else if (element.webkitRequestFullscreen) { |
| element.webkitRequestFullScreen(); |
| } |
| } |
| |
| launchFullscreen(document.documentElement); |
| launchFullscreen(document.getElementById("id")); |
260退出全屏
| function exitFullscreen() { |
| if (document.exitFullscreen) { |
| document.exitFullscreen(); |
| } else if (document.msExitFullscreen) { |
| document.msExitFullscreen(); |
| } else if (document.mozCancelFullScreen) { |
| document.mozCancelFullScreen(); |
| } else if (document.webkitExitFullscreen) { |
| document.webkitExitFullscreen(); |
| } |
| } |
| |
| exitFullscreen(); |
261全屏事件
| document.addEventListener("fullscreenchange", function (e) { |
| if (document.fullscreenElement) { |
| console.log("进入全屏"); |
| } else { |
| console.log("退出全屏"); |
| } |
| }); |
数字 Number
262.数字千分位分割
| function commafy(num) { |
| return num.toString().indexOf(".") !== -1 |
| ? num.toLocaleString() |
| : num.toString().replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); |
| } |
| commafy(1000) |
263.生成随机数
| function randomNum(min, max) { |
| switch (arguments.length) { |
| case 1: |
| return parseInt(Math.random() * min + 1, 10); |
| case 2: |
| return parseInt(Math.random() * (max - min + 1) + min, 10); |
| default: |
| return 0; |
| } |
| } |
| randomNum(1,10) |
264 时间戳转时间
| |
| function timestampToTime(cjsj) { |
| var date = new Date(cjsj); |
| var Y = date.getFullYear() + '-'; |
| var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; |
| var D = (date.getDate() + 1 < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '; |
| return Y + M + D |
| } |
265 过滤富文本和空格为纯文本
| |
| function filterHtml(str) { |
| return str.replace(/<[^<>]+>/g, '').replace(/ /ig, ''); |
| } |
266 指定显示的文字数量多余的使用省略号代替
| |
| function strEllp(str, num = str.length) { |
| var subStr = str.substring(0, num); |
| return subStr + (str.length > num ? '...' : ''); |
| } |
267 获取滚动条当前的位置
| |
| function getScrollTop() { |
| var scrollTop = 0 |
| if (document.documentElement && document.documentElement.scrollTop) { |
| scrollTop = document.documentElement.scrollTop; |
| } else if (document.body) { |
| scrollTop = document.body.scrollTop; |
| } |
| return scrollTop |
| } |
268 获取当前可视范围的高度
| |
| function getClientHeight() { |
| var clientHeight = 0 |
| if (document.body.clientHeight && document.documentElement.clientHeight) { |
| clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight) |
| } else { |
| clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight) |
| } |
| return clientHeight |
| } |
269 获取文档完整的高度
| |
| function getScrollHeight() { |
| return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight) |
| } |
细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」
细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」
细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」
细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」
细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」
细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」