JS中常用高级函数整理

发布时间:2020-01-12 18:06:58阅读:(102)

一、防抖动与节流

针对一些会频繁触发的事件,入resize,keypress,scroll等,如果正常绑定时间处理函数的话,很可能在段时间内连续触发多次,极大的浪费资源,降低前端性能。因此针对这类事件需要进行防抖动或节流处理。

防抖动

它的做法是限制下次函数调用之前必须等待的时间间隔。正确实现 debouncing 的方法是将若干个函数调用合成 一次,并在给定时间过去之后仅被调用一次。

function debounce(func, delay, immediate){
var timer = null;
return function (){
var _this = this;
var args = arguments;
if(timer){
clearTimeout(timer);
}
if(immediate){
//根据距离上次触发操作的时间是否到达delay来决定是否要现在执行函数
var doNow = !timer;
//每一次都重新设置timer,就是要保证每一次执行的至少delay秒后才可以执行
timer = setTimeout(function(){
timer = null;
},delay);
//立即执行
if(doNow){
func.apply(_this, args);
}
}else{
timer = setTimeout(function(){
func.apply(_this, args);
}, delay);
}
}
}

用法:

var run = function(){
console.log("You are scrolling!");
}

let elem = document.getElementById('container');
// 滚动完成2秒后触发
elem.addEventListener('scroll', debounce(foo, 2000));
// 一滚动立即触发一次
elem.addEventListener('scroll', debounce(foo, 2000, true));

节流

节流是另一种处理类似问题的解决方法。

节流函数允许一个函数在规定的时间内只执行一次。

它和防抖动最大的区别就是,节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

应用场景:输入框的联想,可以限定用户在输入时,只在两秒钟响应一次联想

实现方式一,时间戳实现:

var throttle = function(func, delay){
var prev = Date.now();
return function(){
var _this = this;
var args = arguments;
var now = Date.now();
if(now-prev>=delay){
func.apply(_this, args);
prev = Date.now();
}
}
}

实现方式二,定时器实现:

var throttle = fucntion(func,delay){
var timer = null;
return funtion(){
var _this = this;
var args = arguments;
if(!timer){
timer = setTimeout(function(){
func.apply(_this,args);
timer = null;
},delay);
}
}
}

实现方式三,结合使用,效果:一个事件触发时立即执行,触发完毕还能执行一次的节流函数

var throttle = function(func,delay){
var timer = null;
var startTime = Date.now();
return function(){
var curTime = Date.now();
var remaining = delay-(curTime-startTime);
var _this = this;
var args = arguments;
clearTimeout(timer);
if(remaining<=0){
func.apply(_this,args);
startTime = Date.now();
}else{
timer = setTimeout(func,remaining);
}
}
}

二、数组扁平化

function flattenDepth(array, depth = 1){
let result = [];
array.forEach(item => {
let d = depth;
if(Array.isArray(item) && d > 0) {
result.push(...(flattenDepth(item, --d)));
} else {
result.push(item);
}
});
return result;
}

用法:

console.log(flattenDepth([1,[2,[3,[4]],5]));
// > [1,2,3,4,5]

三、柯里化

柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围(自维基百科)

实现:

function curry(func){
var l = func.length;
return function curried() {
var args = [].slice.call(arguments);
if(args.length < 1){
return function () {
var argsInner = [].slice.call(arguments);
return curried.apply(this, args.concat(argsInner))
}
}else{
return func.apply(this, args)
}
}
}

使用场景:

function square(i) {
return i * i;
}

function dubble(i) {
return i *= 2;
}

function map(handeler, list) {
return list.map(handeler);
}

// 数组的每一项平方
map(square, [1, 2, 3, 4, 5]);
map(square, [6, 7, 8, 9, 10]);

// 数组的每一项加倍
map(dubble, [1, 2, 3, 4, 5]);
map(dubble, [6, 7, 8, 9, 10]);

// 利用柯里化改造后
var mapSQ = curry(map, square);
mapSQ([1, 2, 3, 4, 5]);
mapSQ([6, 7, 8, 9, 10]);

var mapDB = curry(map, dubble);
mapDB([1, 2, 3, 4, 5]);
mapDB([6, 7, 8, 9, 10]);

四、对象拷贝

function clone(value, isDeep){
if(value === null) return null;
if(typeof value !== 'object') return value
if(Array.isArray(value)){
if(isDeep){
return value.map(item => clone(item, true))
}
return [].concat(value)
}else{
if(isDeep){
var obj = {};
Object.keys(value).forEach(item => {
obj[item] = clone(value[item], true)
});
return obj;
}
return {...value}
}
}
标签:js

发表评论

评论列表(有0条评论102人围观)
暂无评论