JS 常用技术
叶江怀 2021-02-18 javascript
# JS 常用技术
# 防抖
/*
防抖:
@params:
func[function]:最后要触发执行的函数
wait[number]:频繁设定的界限
immediate[boolean]:默认多次操作,我们识别的是最后一次,但是immediate=true,让其识别第一次
@return
可以被调用执行的函数
*/
export const debounce = (func, wait = 200, immediate = false) => {
let timer = null;
return (anonymous = (...parmas) => {
let now = immediate && !timer;
// 每次点击时都有清楚掉原有的定时器
clearTimeout(timer);
timer = setTimeout(() => {
timer = null; //垃圾回收机制
// 判断时候二次触发
!immediate ? func.call(this, ...parmas) : null;
}, wait);
!now ? func.call(this, ...parmas) : null;
});
};
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
# 节流
/*
@params:
func[function]:最后要触发执行的函数
wait[number]:触发的频率
@return
可以被调用执行的函数
*/
throttle = (func, wait = 300) => {
let timer = null,
previous = 0; //记录上一次操作时间
return function anonymouse(...params) {
let now = new Date(), //记录当前时间
remaining = wait - (now - previous); //记录还差多久达到我们一次触发的频率
if (remaining <= 0) {
//两次操作的间隔时间已经超过wait了
window.clearInterval(timer);
timer = null;
previous = now;
func.call(this, ...params);
} else if (!timer) {
//两次操作的间隔时间还不符合触发的频率
timer = setTimeout(() => {
timer = null;
previous = new Date();
func.call(this, ...params);
}, remaining);
}
};
};
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
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
# 深拷贝
// 1、利用JSON进行深拷贝
export const deepClone1 = (obj) => {
return JSON.parse(JSON.stringify(obj));
};
// 2、利用递归进行深拷贝
export const deepClone = (obj, cache = new Set()) => {
//深克隆 cache处理self属性,防止死递归
//只有数组和对象我们再处理深克隆,其余的按照浅克隆
let type = toType(obj);
if (!/^(array|object)$/.test(type)) return this.clone(obj);
if (cache.has(obj)) return obj;
cache.add(obj);
let keys = this.getOwnProperty(obj),
clone = {};
type === "array" ? (clone = []) : null;
keys.forEach((key) => {
clone[key] = this.deepClone(obj[key], cache);
});
return clone;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 数组扁平化处理
let arr = [1, 2, [3, 4, [5, [6]]]];
// 1、使用flat
export const flatArr = (arr) => {
return arr.flat(Infinity); //flat参数为指定要提取嵌套数组的结构深度,默认值为 1
};
// 2、使用reduce
function reduceArr(arr) {
return arr.reduce((prev, cur) => {
return prev.concat(Array.isArray(cur) ? reduceArr(cur) : cur);
}, []);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 数组去重
const arr = [1, 1, "1", 17, true, true, false, false, "true", "a", {}, {}];
// => [1, '1', 17, true, false, 'true', 'a', {}, {}]
// 1、利用嵌套循环和splice
export const unique1 = (arr) => {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
// 每删除一个树,j--保证j的值经过自加后不变。同时,len--,减少循环次数提升性能
len--;
j--;
}
}
}
return arr;
};
// 利用indexOf
export const unique2 = (arr) => {
const res = [];
for (let i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) res.push(arr[i]);
}
return res;
};
// 利用es6的Set
export const unique3 = (arr) => {
return Array.from(new Set(arr));
};
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
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
# 函数珂里化
export const add = () => {
let _args = [...arguments];
fn = () => {
_args.push(...arguments);
return fn;
};
fn.toString = () => {
return _args.reduce((sum, cur) => sum + cur);
};
return fn;
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# AJAX
export const getJSON = (url) => {
return new Promise((resolve, reject) => {
const xhr = XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Mscrosoft.XMLHttp");
xhr.open("GET", url, false);
xhr.setRequestHeader("Accept", "application/json");
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status === 200 || xhr.status === 304) {
resolve(xhr.responseText);
} else {
reject(new Error(xhr.responseText));
}
};
xhr.send();
});
};
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
# 图片懒加载
lazyload = () => {
const imgs = document.getElementsByTagName("img");
const len = imgs.length;
// 视口的高度
const viewHeight = document.documentElement.clientHeight;
// 滚动条高度
const scrollHeight =
document.documentElement.scrollTop || document.body.scrollTop;
for (let i = 0; i < len; i++) {
const offsetHeight = imgs[i].offsetTop;
if (offsetHeight < viewHeight + scrollHeight) {
const src = imgs[i].dataset.src;
imgs[i].src = src;
}
}
};
// 可以使用节流优化一下
window.addEventListener("scroll", lazyload);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19