最近重温了一遍红宝书,发现一些比较好玩的写法,很多东西日常都在用,但是发现还会有不一样的写法,结合一些日常工作中使用的方法,为大家总结一篇日常经常使用可能还不知道的点,希望对你能有所帮助:
一行代码完成结构加赋值
我们日常经常使用结构赋值,一般都是先结构,再赋值,当然我们也可以一行就完成解构加赋值操作,看起来非常简化,当然可读性你懂得!
let people = { name: null, age: null };
let result = { name: '张三', age: 16 };
({ name: people.name, age: people.age} = result);
console.log(people) // {"name":"张三","age":16}###
对基础数据类型进行解构
日常中我们应该用不到这样的场景,但是实际上我们也可以对基础数据类型解构
const {length : a} = '1234';
console.log(a) // 4
对数组解构快速拿到最后一项值
实际上我们是可以对数组解构赋值拿到length属性的,通过这个特性也可以做更多的事情。
const arr = [1, 2, 3];
const { 0: first, length, [length - 1]: last } = arr;
first; // 1
last; // 3
length; // 3
将下标转为中文零一二三…
日常可能有的列表我们需要将对应的012345转为中文的一、二、三、四、五…,在老的项目看到还有通过自己手动定义很多行这样的写法,于是写了一个这样的方法转换
export function transfromNumber(number){
const INDEX_MAP = ['零','一'.....]
if(!number) return
if(number === 10) return INDEX_MAP[number]
return [...number.toString()].reduce( (pre, cur) => pre + INDEX_MAP[cur] , '' )
}
判断整数的不同方法
/* 1.任何整数都会被1整除,即余数是0。利用这个规则来判断是否是整数。但是对字符串不准确 */
function isInteger(obj) {
return obj%1 === 0
}
/* 1. 添加一个是数字的判断 */
function isInteger(obj) {
return typeof obj === 'number' && obj%1 === 0
}
/* 2. 使用Math.round、Math.ceil、Math.floor判断 整数取整后还是等于自己。利用这个特性来判断是否是整数*/
function isInteger(obj) {
return Math.floor(obj) === obj
}
/* 3. 通过parseInt判断 某些场景不准确 */
function isInteger(obj) {
return parseInt(obj, 10) === obj
}
/* 4. 通过位运算符*/
function isInteger(obj) {
return (obj | 0) === obj
}
/* 5.ES6提供了Number.isInteger */
通过css检测系统的主题色从而全局修改样式
@media 的属性 prefers-color-scheme就可以知道当前的系统主题,当然使用前需要查查兼容性
@media (prefers-color-scheme: dark) { //... }
@media (prefers-color-scheme: light) { //... }
javascript也可以轻松做到
window.addEventListener('theme-mode', event =>{
if(event.mode == 'dark'){}
if(event.mode == 'light'){}
})
window.matchMedia('(prefers-color-scheme: dark)') .addEventListener('change', event => {
if (event.matches) {} // dark mode
})
数组随机打乱顺序
通过 0.5-Math.random() 得到一个随机数,再通过两次sort排序打乱的更彻底,但是这个方法实际上并不够随机,如果是企业级运用,建议使用第二种洗牌算法
shuffle(arr) {
return arr.sort(() => 0.5 - Math.random()). sort(() => 0.5 - Math.random());
},
function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const randomIndex = Math.floor(Math.random() * (i + 1))
;[arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]]
}
return arr
}
随机获取一个Boolean值
和上个原理相同,通过随机数获取,**Math.random()**的区间是0-0.99,用0.5在中间百分之五十的概率
function randomBool() {
return 0.5 - Math.random()
}
把数组最后一项移到第一项
function (arr){
return arr.push(arr.shift());
}
把数组的第一项放到最后一项
function(arr){
return arr.unshift(arr.pop());
}
利用set数组去重
function uniqueArr(arr){
return [...new Set(arr)]
}
dom节点平滑滚动到可是区域,顶部,底部
原生的scrollTo方法没有动画,类似于锚点跳转,比较生硬,可以通过这个方法会自带平滑的过度效果
function scrollTo(element) {
element.scrollIntoView({ behavior: "smooth", block: "start" }) // 顶部
element.scrollIntoView({ behavior: "smooth", block: "end" }) // 底部
element.scrollIntoView({ behavior: "smooth"}) // 可视区域
}
获取随机颜色
日常我们经常会需要获取一个随机颜色,通过随机数即可完成
function getRandomColor(){
return `#${Math.floor(Math.random() * 0xffffff) .toString(16)}`;
}
检测是否为空对象
通过使用Es6的Reflect静态方法判断他的长度就可以判断是否是空数组了,也可以通过**Object.keys()**来判断
function isEmpty(obj){
return Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;
}
Boolean转换
一些场景下我们会将boolean值定义为场景,但是在js中非空的字符串都会被认为是true
function toBoolean(value, truthyValues = ['true']){
const normalizedValue = String(value).toLowerCase().trim();
return truthyValues.includes(normalizedValue);
}
toBoolean('TRUE'); // true
toBoolean('FALSE'); // false
toBoolean('YES', ['yes']); // true
复制代码
各种数组克隆方法
数组克隆的方法其实特别多了,看看有没有你没见过的!
const clone = (arr) => arr.slice(0);
const clone = (arr) => [...arr];
const clone = (arr) => Array.from(arr);
const clone = (arr) => arr.map((x) => x);
const clone = (arr) => JSON.parse(JSON.stringify(arr));
const clone = (arr) => arr.concat([]);
const clone = (arr) => structuredClone(arr);
比较两个时间大小
通过调用getTime获取时间戳比较就可以了
function compare(a, b){
return a.getTime() > b.getTime();
}
计算两个时间之间的月份差异
function monthDiff(startDate, endDate){
return Math.max(0, (endDate.getFullYear() - startDate.getFullYear()) * 12 - startDate.getMonth() + endDate.getMonth());
}
一步从时间中提取年月日时分秒
时间格式化轻松解决,一步获取到年月日时分秒毫秒,由于toISOString会丢失时区,导致时间差八小时,所以在格式化之前我们加上八个小时时间即可
function extract(date){
const d = new Date(new Date(date).getTime() + 8*3600*1000);
return new Date(d).toISOString().split(/[^0-9]/).slice(0, -1);
}
console.log(extract(new Date())) // ['2022', '09', '19', '18', '06', '11', '187']
判断一个参数是不是函数
有时候我们的方法需要传入一个函数回调,但是需要检测其类型,我们可以通过Object
的原型方法去检测,当然这个方法可以准确检测任何类型。
function isFunction(v){
return ['[object Function]', '[object GeneratorFunction]', '[object AsyncFunction]', '[object Promise]'].includes(Object.prototype.toString.call(v));
}
计算两个坐标之间的距离
function distance(p1, p2){
return `Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
检测两个dom节点是否覆盖重叠
有些场景下我们需要判断dom是否发生碰撞了或者重叠了,我们可以通过getBoundingClientRect获取到dom的x1,y1,x2,y2坐标然后进行坐标比对即可判断出来
function overlaps = (a, b) {
return (a.x1 < b.x2 && b.x1 < a.x2) || (a.y1 < b.y2 && b.y1 < a.y2);
}
判断是否是NodeJs环境
前端的日常开发是离不开nodeJs的,通过判断全局环境来检测是否是nodeJs环境
function isNode(){
return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
}
参数求和
之前看到有通过函数柯理化形式来求和的,通过reduce一行即可
function sum(...args){
args.reduce((a, b) => a + b);
}
数组去重
从数组中删除所有重复值,实现方式非常多,我们这里就说最简单的方式,一行代码搞定:
const uniqueArr = (arr) => [...new Set(arr)];
console.log(uniqueArr(["前端","js","html","js","css","html"]));
// ['前端', 'js', 'html', 'css']
复制代码
uniqueArr
方法将数据转为Set,然后再解构为数组返回。
从url获取参数并转为对象
网页路径经常是:www.baidu.com?search=js&xxx=kkk
这种形式的,我们是经常需要取参数的,可以使用第三方的qs
包实现,如果你只是要实现去参数,这一句代码就可以实现,不用再引入qs
了。
const getParameters = URL => JSON.parse(`{"${decodeURI(URL.split("?")[1]).replace(/"/g, '\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`
)
getParameters("https://www.google.com.hk/search?q=js+md&newwindow=1");
// {q: 'js+md', newwindow: '1'}
复制代码
检查对象是否为空
检查对象是否为空,实际上并不那么简单,即使对象为空,每次检查对象是否等于 {}
也会返回 false
。
幸运的是,下面的单行代码正是我们想要的。
const isEmpty = obj => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;
isEmpty({}) // true
isEmpty({a:"not empty"}) //false
复制代码
反转字符串
反转字符串可以使用split
结合reverse
和join
方法轻松实现。
const reverse = str => str.split('').reverse().join('');
reverse('this is reverse');
// esrever si siht
复制代码
生成随机十六进制
生成随机数相信你能信手拈来,那随机生成十六进制,例如生成十六进制颜色值。
const randomHexColor = () => `#${Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0")}`
console.log(randomHexColor());
// #a2ce5b
复制代码
检查当前选项卡是否在后台
浏览器使用选项卡式浏览,任何网页都有可能在后台,此时对用户来说是没有在浏览的, 知道怎么快速检测到,你的网页对用户是隐藏还是可见吗?
const isTabActive = () => !document.hidden;
isTabActive()
// true|false
复制代码
检测元素是否处于焦点
activeElement
属性返回文档中当前获得焦点的元素。
const elementIsInFocus = (el) => (el === document.activeElement);
elementIsInFocus(anyElement)
// 元素处于焦点返回true,反之返回false
复制代码
检查设备类型
使用navigator.userAgent
判断是移动设备还是电脑设备:
const judgeDeviceType =
() => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|OperaMini/i.test(navigator.userAgent) ? 'Mobile' : 'PC';
judgeDeviceType() // PC | Mobile
文字复制到剪贴板
Clipboard API
它的所有操作都是异步的,返回 Promise
对象,不会造成页面卡顿。而且,它可以将任意内容(比如图片)放入剪贴板。
const copyText = async (text) => await navigator.clipboard.writeText(text)
copyText('单行代码 前端世界')
获取选定的文本
使用内置的 getSelection
获取用户选择的文本:
const getSelectedText = () => window.getSelection().toString();
getSelectedText();
// 返回选中的内容
查询某天是否为工作日
我们自己写日历组件时经常会用到,判断某个日期是否为工作日;周一至周五为工作日:
const isWeekday = (date) => date.getDay() % 6 !== 0;
isWeekday(new Date(2022, 03, 11))
// true
转换华氏/摄氏
处理温度有时会晕头转向。这两个函数则能帮助大家将华氏温度转换为摄氏温度,以及将摄氏温度转换为华氏温度。
- 将华氏温度转换为摄氏温度
const fahrenheitToCelsius = (fahrenheit) => (fahrenheit - 32) * 5/9;
fahrenheitToCelsius(50);
// 10
复制代码
- 将摄氏温度转华氏温度
const celsiusToFahrenheit = (celsius) => celsius * 9/5 + 32;
celsiusToFahrenheit(100)
// 212
复制代码
两日期之间相差的天数
日常开发中经常遇到需要显示剩余天数, 一般我们就需要计算两日期之间相差天数:
const dayDiff = (date1, date2) => Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000);
dayDiff(new Date("2021-10-21"), new Date("2022-02-12"))
// Result: 114
复制代码
将 RGB 转换为十六进制
const rgbToHex = (r, g, b) => "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
rgbToHex(255, 255, 255);
// #ffffff
复制代码
计算数组平均值
计算平均值的方式很多,计算的逻辑都是一样的, 但是实现方式各不相同,一行代码简单实现:
const average = (arr) => arr.reduce((a, b) => a + b) / arr.length;
average([1,9,18,36]) //16