安利一下日常开发中JS的小技巧
前言
今天给大家安利一波我在做前端开发(crtl+c/v)
中的一些提升幸福度 js
使用小技巧,它可以帮助你书写干净和优雅的JavaScript
代码。
类型转换
// 字符转数字
'32' * 1 // 32
null * 1 // 0
undefined * 1 // NaN
// 转字符串
'' + 32 // '32'
'' + undefined // 'undifined'
'' + null // 'null'
// 时间戳
+new Date() // 1656041075862
tips
:利用 js
运算符中的隐式转换,在做运算的时候会根据运算符的不同对数据做不同的转换。
多值分配
const [a, b, c] = [1, 'hi', true] // a = 1 , b = 'hi' , c = true
const [x, ...y] = [1, 2, 3]; // x = 1 , y = [2, 3]
tips
:利用数组的结构赋值(对象结构也可以)。
取整
5.8 | 0 // 5
-5.8 | 0 // 5
tips
:利用计算机中二进制按位或进行计算(注意,如果n
为正,则n | 0
是向下舍入,如果n
为负数,则是向上舍入),~~
(双非按位取反运算) 也可以达到类似效果。
奇偶数
const num = 13;
if (num & 1) console.log("odd");
else console.log("even"); // odd
tips
:利用计算机中二进制按位与运算,通过 & 1
,可以得出 奇数(十进制)
位与1
的结果是1
,偶数(十进制)
位与1
的结果是0
。
&& 和 ||
const a = true && 4 && "a"; // a
const b = true && 0 && "b"; // 0
const c = 1 || 2; // 1
const d = "d" || "hi"; // 'd'
const e = "" || "hi"; // 'hi'
// 常用于回调函数调用
cb && cb() // cb 存在执行 cb 方法
tips
: 利用逻辑运算符的特性,可以实现降低代码的
&& :从左往右依次判断,当当前值为 true 则继续,为 false 则返回此值。
|| :从左往右依次判断,当当前值为 false 则继续,为 true 则返回此值。
?? 运算符
0 ?? 2 // 0
1 ?? 2 // 1
false ?? 2 // false
null ?? 2 // 2
undefined ?? 2 // 2
tips
:某些情况可以用 ??
来替代 ||
,因为 ??
判断运算符左侧的值为null
或 undefined
时,才返回右侧的值,可以处理 0
, false
的情况。
UniqueID 生成器
Math.random().toString(36).slice(8)
tips
:利用toSring
函数将随机数转换为一个36进制
字符串,在通过slice
函数截取小数点以后的字符。
uuid 生成器
const uuid = crypto.randomUUID(); // '460e025e-cf90-47c0-a2a3-f920755d63c5'
tips
:利用 Web Crypto 提供的加密接口,可以很方便的使用其 api
生成 uuid
。
数组过滤 False
类型值
const arr = [false, null, 0, "", undefined, NaN, 1, 2, 3]
const nArr = arr.filter(Boolean) // [1,2,3]
tips
:利用 Boolean
函数对数组中的元素进行转换后过滤。
数组去重
const arr = [1,2,3,3,2,1]
const uArr= [...new Set(arr)] // [1,2,3]
tips
:利用 ES6
中 Set
数据结构不重复的特性。
数组乱序
const arr = [1, 2, 3, 4, 5, 6, 7, 8];
arr.sort(() => Math.random() - 0.5) // [5, 4, 3, 2, 6, 8, 1, 7]
tips
:利用数组自带的 sort
函数通过随机数的比较来打乱(会改变原始数组)。
数组求和
const arr = [1,2,3]
const sum = arr.reduce((x, y) => x + y) // 6
tips
:利用 reduce
函数收敛的特性,传入一个累加函数,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
数组交集
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [2, 3, 4];
arr1.filter(v => arr2.includes(v)); // [2, 3, 4]
tips
:利用数组 filter
和 includes
函数过滤过存在于另一个数组中的元素,求交集。
数组并集
const arr1 = [1, 2, 3];
const arr2 = [2, 3, 4];
arr1.concat(arr2.filter(v => !arr1.includes(v))); // [1, 2, 3, 4]
tips
:利用数组 concat
和 includes
函数拼接另一个数组中不存在的元素,求并集。
数组差集
const arr1 = [1, 2, 3, 4]
const arr2 = [2, 3, 5, 6];
arr1.filter(v => !arr2.includes(v)); // [1, 4]
tips
:arr1
利用 filter
函数过滤出不存在于 arr2
中的元素,得到差集。
数组补集
const arr1 = [1, 2, 3, 4]
const arr2 = [2, 3, 5, 6];
Array.from(new Set(arr1.concat(arr2).filter(v => !new Set(arr1).has(v) || !new Set(arr2).has(v)))) // [1, 4, 5, 6]
tips
:先通过concat
拼接两数组后,然后再通过filter
函数分别过滤过不存在于自身内的元素,得到其补集。
格式化金额
const num = 100010001;
num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); // 100,010,001
tips
:利用 replace
函数做正则匹配每匹配到三位数字添加一个,
。
补0
const fillZero = (num, len) => num.toString().padStart(len, "0");
fillZero(9, 2); // 09
tips
:利用padStart
函数补全字符串长度,可以达到不够补0
的情况,可以格式化时间等。
保留小数
const round = (num, decimal) => Math.round(num * 10 ** decimal) / 10 ** decimal;
round(12.453,2); // 12.45
round(12.457,2); // 12.46
tips
:利用进行指数倍增,再指数缩减的方式,可以实现保留任意位数小数,还可以避免精度丢失的问题。
判断数据类型
const type = (val) => Object.prototype.toString.call(val).slice(8, -1);
type(1); // Number
type('s'); // String
type(false); // Boolean
type([]); // Array
type({}); // Object
type(new Date()); // Date
type(Symbol(0)); // Symbol
type(undefined); // Undefined
type(null); // Null
tips
:利用 Object.prototype.toString.call
方法可以准确判断数据类型
获取URL参数
const urlSearch = '?name=tom&age=18&id=1&id=2';
const urlParams = new URLSearchParams(urlSearch);
urlParams.get('name'); // tom
urlParams.has('age'); // true
urlParams.get('xx'); // null
urlParams.toString(); // name=tom&age=18&id=1&id=2
urlParams.getAll('id'); // ['1','2']
urlParams.append('method', 'get');
urlParams.toString(); // name=tom&age=18&id=1&id=2&method=get
tips
:利用 URLSearchParams()
构造器创建并返回一个新的 URLSearchParams 对象,可以很方便的获取url
参数,还有类似Object.keys()
,Object.values()
等方法。
图片懒加载
const lazyLoad = function () {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if ( entry.intersectionRatio > 0 ) {
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target)
}
})
})
Array.from(document.getElementsByTagName('img')).forEach(el => {
observer.observe(el)
})
}
tips
:利用 IntersectionObserver()
构造器创建并返回一个IntersectionObserver
对象,通过观察 intersectionRatio
的状态来确定目标是否在视口内。
结语
以上是我大概整理的一些开发中的技巧和方法,可以发现里面涉及到了很多新的es
特性和 api
,使用时可要记得兼容性哦,感兴趣的小伙伴可自行查阅学习,也欢迎小伙伴们一起交流探讨,加油!