JS常见高级函数
# 1. 节流函数
在规定的一个单位时间内,事件只能触发一次;如果单位内触发多次函数,只有一次生效。
function throttle(func, ms) {
let timer = null;
return function () {
let that = this;
let args = arguments;
if (!timer) {
timer = setTimeout(() => {
timer = null;
func.apply(that, args);
}, ms);
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 2. 防抖函数
在事件被触发后 n 秒内再执行回调,如果 n 秒内再次触发,则重新计时。
function debounce(func, ms) {
let timer = null;
return function () {
let that = this;
let args = arguments;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(that, args);
}, ms);
};
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 3. 深拷贝
对于数组、对象等类型时引用类型,变量标识符存储的指针指向堆中的对象,需要深拷贝赋值。
function copy(obj) {
let newObj = null;
if (typeof obj == "object" && typeof obj !== null) {
newObj = obj instanceof Array ? [] : {};
for (let i in obj) {
newObj[i] = copy(obj[i]);
}
} else {
newObj = obj;
}
return newObj;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
更加严谨的写法:
function deepClone(obj={}){
if(tyoeof obj !== 'object') { return obj;}
let result = {};
if(obj instanceof Array || Object.prototype.toString().call(obj) === '[object Arrray]') { result = [];}
for(const key in obj) {
if(obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key]);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 手写 Promise.all
function PromiseAll(arr) {
// 将可迭代对象转换成一个数组
let promises = Array.from(arr);
const data = [];
let index = 0,
len = promises.length;
return new Promise((resolve, reject) => {
for (let i in promises) {
// 需要并发执行,需要先resolve执行每个promise,再then
Promise.resolve(promises[i])
.then((res) => {
// 不要用push,用下标存储,保证输出的顺序
data[i] = res;
if (++index === len) {
resolve(data);
}
})
.catch((err) => {
reject(err);
});
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
扩展:手写 Promise.race:
function promiseRace(iterator) {
const promises = Array.from(iterator);
return new Promise((resolve, reject) => {
for (const i in promises) {
Promise.resolve(promises[i])
.then((res) => resolve(res))
.catch((err) => reject(err));
}
});
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
手写 Promise.allSettled:
const myPromiseAllSettled(iterator) {
return new Promise((resolve, reject) => {
if(!Array.isArray(iterator)) {
return reject(new Error('params is not an iteraor Array'))
}
let res = [],count = 0;
for(let i=0;i<iterator.length;i++) {
Promise.resolve(iterator[i]).then(value => {
res[i] = {status: fulfilled, value};
}).catch(err => {
res[i] = {status:reject,err};
}).finally(() => {
count++;
if(count === iterator.length) {
resolve(res);
}
})
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 5. 大数之和
尽量避免采用 BigInt 类型,比如说 QQ 好像就不支持,一般采用通用方法。
function add(a, b) {
let n = Math.max(a.length, b.length);
a = a.padStart(n, 0);
b = b.padStart(n, 0);
let carry = 0;
let res = "";
for (let i = n - 1; i >= 0; i--) {
let t = parseInt(a[i]) + parseInt(b[i]) + carry;
carry = Math.floor(t / 10);
t = t % 10;
res = t + res;
}
if (carry === 1) {
res = "1" + res;
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 6. 扁平化数组
const flat = arr => arr.flat();
const flat = arr => arr.reduce((a,b) => Array.isArray(b) ? [...a,...flat(b)] : [...a,b],[]);
// 指定深度
const flat = (arr, dep = 1) => {
if(dep > 0) {
return arr.reduce((a,b) => Array.isArray(b) ? [...a,...flat(b,dep-1)] : [...a,b], []);
}else {
return arr;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 7. 保证对象数据不可修改
const定义的变量是常量,如果定义的是基本类型数据,则变量指向的内存地址中存储的就是该值,不可修改;但是如果是对象类型的话,变量中存储的是指针,该指针指向存储的数据,此时就只能保证指针是固定的,指向的数据还是可以改变的,如何保证复合类型的值不可修改呢?可以使用Object.freeze()方法。
const constantize = obj => {
Object.freeze(obj);
Object.keys(obj).forEach(key => {
if(typeof obj[key] === 'object') {
constantize(obj[key]);
}
})
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
参考链接:
编辑 (opens new window)
上次更新: 2022/06/16, 10:52:37