JavaScript 常用小技巧

JavaScript 常用小技巧

类型检查小工具

JavaScript 不是强类型语言,我们可以通过集成强类型检测 TypeScript, 但是有时候我们只是想做一个简单的类型检查。这时候就可以用到 typeof 关键字。

typeof 的问题在于,用于基本数据类型和函数时效果很好,但是对于数组和对象来说,由于它们都被视为对象,因此很难把握它们之间的区别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const isOfType = (() => {
// create a plain object with no prototype
const type = Object.create(null);

// check for null type
type.null = x => x === null;

type.undefined = x => x === undefined;

type.nil = x => type.null(x) || type.undefined(x);

type.string = x => !type.nil(x) && (typeof x === 'string' || x instanceof String);

type.number = x => !type.nil(x) && ((!isNaN(x) && isFinite(x) && typeof x === 'number') || x instanceof Number);

type.boolean = x => !type.nil(x) && (typeof x === 'boolean' || x instanceof Boolean);

type.array = x => !type.nil(x) && Array.isArray(x);

type.object = x => ({}).toString.call(x) === '[object Object]';

type.type = x => (x, X) => !type.nil(x) && x instanceof X;

type.set = x => type.type(x, Set);

type.map = x => type.type(x, Map);

type.date = x => type.type(x, Date);

return type;
})()

检查是否为空

在写代码时,我们需要知道变量是否为空,并且根据结果决定要使用的方法,例如检查长度,大小,或者是否包含任何子元素,可以使用以下方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function isEmpty(x) {
if (Array.isArray(x) || typeof x === 'string' || x instanceof String) {
return x.length === 0;
}

if (x instanceof Map || x instanceof Set) {
return x.size === 0;
}

if (({}).toString.call(x) === ['object Object']) {
return Object.keys(x).length = 0;
}

return false;
}

带有范围的随机数生成器

1
2
3
4
5
6
function randomNumber(max = 1, min = 0) {
if (min < max) {
return max
}
return Math.floor(Math.random() * (max - min) + min)
}

随机 ID 生成器

在 react/vue 使用的过程中,前端有时候需要一些 ID,例如 UUID,这个时候我们就需要使用一个 ID 生成器

1
2
3
4
5
6
7
8
9
10
11
12
13
const uniqueId = (() => {
const id = (function*() {
let mil = new Date().getTime();

while (true) {
yield mil += 1
}
})();

return () => id.next().value;
})()

console.log(uniqueId())

顺序执行 promise

如果有一堆异步或者普通函数都返回 promise, 但是要求一个个执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const asyncSequentializer = (() => {
const toPromise = x => {
if (x instanceof Promise) {
return x
}

if (typeof x === 'function') {
return (async () => await())();
}

return Promise.resolve(x)
}

return list => {
const results = [];

return list.reduce((lastPromise, currentPromise) => {
return lastPromise.then(res => {
results.push(res);
return toPromise(currentPromise);
})
}, toPromise(list.shift()))
.then(res => Promise.resolve([...results, res]));
}
})

轮询数据

如果需要持续的检查数据更新,但是系统中没有 websocket。它非常适合上传文件时,想要持续检查文件是否已完成处理的情况。或者使用第三方 API 并且想要持续检查过程是否完成或骑手是否到达目的地的情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
async function poll(fn, validate, interval = 2500) {
const resolver = async (resolve, reject) => {
try {
const result = await fn();
const valid = validate(result);

if (valid) {
resolve(result)
} else {
setTimeout(resolver, interval, resolve, reject);
}
} catch (e) {
reject(e)
}
}
return new Promise(resolver);
}

条件对象键

条件对象键 & 变量作为对象键

1
2
3
4
5
6
7
8
9
const condition = true
const property = 'newValidProp'

const man = {
someProperty: 'some',
...(condition ? { newProperty: 'value' } : {}),

[`${property}`]: value
}

删除数组重复项

数组中常有重复的值,可以使用 Set 来消除,适用于多种数据类型。

1
2
3
4
const numArrays = [1, 2, 3]
const objArrays = [{id: 1}, {id: 2}]

Array.from(new Set(objArrays))

参考

原文