1、判断是否为数字
const isNum = num => !Number.isNaN(Number.parseFloat(num)) && Number.isFinite(num);
2、判断nums中全部为有效数字
const isNums = (...nums) => !!nums.length && nums.every(i => isNum(i));
console.log(isNums(1, 2, 3)); // true
console.log(isNums()); // false
console.log(isNums(1, null, 3)); // false
console.log(isNums(1, null, "3")); // false
3、判断两个数字的符号是否相同
const isA = (m, n) => isNums(m, n) && (m ^ n) >= 0;
console.log(isA(1, -2)); // false
console.log(isA(-1, 2)); // false
console.log(isA(-1, -2)); // true
console.log(isA(1, 2)); // true
console.log(isA(null, undefined)); // false
4、数组去重
let arr0 = [3, 5, 3, 6, 3, 9];
let arr1 = [...new Set(arr0)];
console.log(arr1); // [ 3, 5, 6, 9 ]
5、数组合并
let arr2 = [8, 5];
console.log([...arr2, 0, 1, ...[3, 2, 4]]) // [ 8, 5, 0, 1, 3, 2, 4 ]
6、判断一个数字是2的整数幂
const isB = n => isNum(n) && (n & (n - 1)) === 0;
console.log(isB(2)); // true
console.log(isB("4")); // true
console.log(isB(6)); // false
console.log(isB(8)); // true
7、函数重载
const fnMap = new Map();
function overLoadFunc(...params){
let key = params.map(p => typeof p).join(",");
let fn = fnMap.get(key);
if(fn){
return fn.apply(this, params);
}else{
throw new Error("no such function");
};
};
overLoadFunc.addImpl = (...params) => {
let fn = params.pop();
if(fn && typeof fn == "function"){
fnMap.set(params.join(","), fn);
}
};
overLoadFunc.addImpl("string", "string", (s1, s2) => {console.log("string", "string", s1, s2)});
overLoadFunc.addImpl("string", "number", (s, num) => {console.log("string", "number", s, num)});
overLoadFunc.addImpl(() => {console.log("empty")});
overLoadFunc("a", "b"); // string string a b
overLoadFunc("a", 1); // string number a 1
overLoadFunc(); // empty
8、倒序遍历
普通方式
let arr = [1, 2];
for (let i = arr.length - 1; i >= 0; i--) {
console.log(arr[i]); // 2 1
}
另一种方式
for (let i = arr.length; i--;) {
console.log(arr[i]); // 2 1
}
9、巧用splice
const rate = n => "★★★★★☆☆☆☆☆".slice(5 - n, 10 - n);
console.log("三星级", rate(3)); // 三星级 ★★★☆☆
10、信号1/0来回切换
普通方式
let _signal = 1;
for (let i = 0; i < 5; i++) {
console.log(_signal++ % 2); // 1 0 1 0 1
}
另一种方式
let signal = 0;
for (let i = 0; i < 5; i++) {
console.log(signal ^= 1); // 1 0 1 0 1
}
11、对象初始化简写
let a = 1;
let b = 2;
let c = { a, b };
console.log(c); // { a: 1, b: 2 }
12、对象取值
let d = { username: "张三", age: "3" };
let { username, age } = d;
console.log(username, age); // 张三 3
13、求一个数字的整数部分
let testNum = 2.66;
console.log(~~testNum); // 2
console.log(testNum | 0); // 2
console.log(testNum >> 0); // 2
console.log(testNum << 0); // 2
14、短路赋值计算
const g = n => (n = +n || 0) && n * 4;
console.log(g()); // 0
console.log(g(null)); // 0
console.log(g(undefined)); // 0
console.log(g("3.1")); // 12.4
console.log(g(3)); // 12
15、一个数乘以2的n次幂
const calculate = (m, n) => m << n;
console.log(calculate(1, 3)); // 8
console.log(calculate(5, 2)); // 20
16、流式计算
let students = [{ un: "张三", sc: 64 }, { un: "张三", sc: 61 }]
const aver = students.length && students.reduce((pre, item) => pre += item.sc, 0) / students.length;
console.log(aver); // 平均分:62.5
17、增加逗号间隔
const formatNum = n => n.replace(/(?=\B(\d{3})+$)/g, ',');
console.log(formatNum("1000000000")); // 1,000,000,000
18、Symbol消除魔法字符串
const MY_TYPE = {
TYPE_1: Symbol("这是一个描述TYPE_1,可为空"),
TYPE_2: Symbol("这是一个描述TYPE_2,可为空")
};
const doSomething = type => {
switch (type) {
case MY_TYPE.TYPE_1:
console.log("执行TYPE_1");
break;
case MY_TYPE.TYPE_2:
console.log("执行TYPE_2");
break;
};
};
doSomething(MY_TYPE.TYPE_1); // 执行TYPE_1
doSomething(MY_TYPE.TYPE_2); // 执行TYPE_2
19、字符码元截取和码点的计算
码元:针对存在单字符为32位长度,即单字符占用两个码元;其他单字符为16位长度,即占用一个码元;
码点:对应码元位置的字符编码,如"a".codePointAt(0)=97,97就是码点;emoji表情的码点都超过了16位即码点大于0xffff
码元 码元 码元 码元 码元 码元 码元 码元 码元 码元 码元 码元 😃 a 😁 b c 😇 c 🙂
String.prototype.customLength = function () {
let len = 0;
for (let i = 0; i < this.length;) {
i += this.codePointAt(i) > 0xffff ? 2 : 1;
len++;
}
return len;
}
String.prototype.customPointAt = function (index) {
let currentIdx = 0;
let code;
if (index < this.customLength()) {
for (let i = 0; i < this.length;) {
code = this.codePointAt(i);
i += code > 0xffff ? 2 : 1;
if (index == currentIdx) {
return String.fromCodePoint(code);
}
currentIdx++;
}
}
return null;
}
String.prototype.customSub = function (start, end) {
let len = this.customLength();
start = (start = ~~start) && start > -1 && start < len + 1 ? start : 0;
end = (end = ~~end) && end > start && end < len + 1 ? end : len;
let str = "";
for (let i = start; i < end; i++) {
str += this.customPointAt(i);
}
return str;
};
let testStr = "😃a😁bc😇c🙂";
// length= 12 customLength=8
console.log("length=", testStr.length, "customLength=" + testStr.customLength());
// index= � customPointAt=😃
console.log("index=", testStr[0], "customPointAt=" + testStr.customPointAt(0));
// substring= 😃a� customLength=😃a😁b
console.log("substring=", testStr.substring(0, 4), "customLength=" + testStr.customSub(0, 4));
20、层叠样式表配合Js使用var
css
<style>
.block {
cursor: pointer;
margin: 100px auto;
width: fit-content;
background: var(--r, green);
}
</style>
html
<div class="block" >
点击切换颜色
</div>
javascript
let signal = 1;
document.querySelector("div.block").onclick = function () {
this.style.setProperty("--r", (signal ^= 1) ? "green" : "gray");
}
效果
21、字符转日期对象
new Date(“2023-07-17”)会默认转为 23/07/17 08:00,所以不使用’-‘,改为’/',这样转才正确;字符错误时date会转为Invalid Date,所以加isNaN判断。
function parseDate(dateStr) {
var _date = dateStr && new Date(dateStr.replace(/-/g, "/"));
return _date && !isNaN(_date.getTime()) ? _date : null;
}