惰性载入函数、函数柯里化、函数节流、函数防抖

不能不写总结

惰性函数
  • 概念理解:最理想的状态下执行一次,后续直接使用第一次执行返回的结果即可。
  • 情景展现:程序初始访问时不确定客户端支持哪种对象,则需要if..else判断,以获取支持的实例化对象。

最典型的的就是浏览器对XHR的实现。

function createXHR(){
	if(typeof XMLHttpRequest!="undefined"){
		return new XMLHttpRequest();
	}else if(typeof ActiveXObject!="undefined"){
		if(typeof arguments.callee.activeXString!="string"){
			var version=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];
			for(var i=0;i<version.length;i++){
				try{
					new ActiveXObject(version[i]);
					arguments.callee.activeXString =version[i];
					break;		
				}catch(ex){
					console.log(ex);	
				}
			}
		}
		return new ActiveXObject(arguments.callee.activeXString);
	}else{
		throw new Error("No XHR valid");	
	}
}

两种方式实现惰性加载:

  1. 函数初始化时,该函数会被内部分支中适配的函数覆盖,下次任何对该函数的调用都是适配好的函数。

    // 一个日志记录的模块
    	function log(){
    		if(user.type==1){
    			log= function(){
    				// 可能是一个对象,好多方法
    				return {
                        print(){
                          console.log("大佬来了!");
                        }
    					
    				}	
    			}
    		}else if(user.type==2){
    			log =function() {
    				// 可能是一个对象,好多方法
    				return {
                      print(){
                        console.log("一个小菜鸟进来了!");
                      }
    					
    				}	
    			}
    		}else{
    			log =function() {
    				throw new Error("未知火星人入侵!");	
    			}
    			
    		}
    		return log();
    	}
    	let user = {
    		// 其他属性
    		type:1,
    	};
    	console.log(log().print());      // "大佬来了"
    
  2. 声明式,由匿名函数返回适配的函数。

     	var log = (function(){
     			if(user.type==1){
     				return function(){
     					// 可能是一个对象,好多方法
     					return {
                             print(){
                               console.log("大佬来了!");
                             }
     					}	
     				}
     			}else if(user.type==2){
     				return function() {
     					// 可能是一个对象,好多方法
     					return {
                           print(){
                             console.log("一个小菜鸟进来了!");
                           }
     						
     					}	
     				}
     			}else{
     				return function() {
     					throw new Error("未知火星人入侵!");	
     				}
     				
     			}
     		})();
    

    匿名函数、自执行的函数注意变量的作用范围,user对象需在之前声明。


函数柯里化

概念:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术——来自百度百科

  • 把接收多个参数的函数分成两步
  • 先传入部分参数由外部函数处理,并返回一个新的函数
  • 再在调用这个新函数传入剩余的参数,进行处理。

先感受一下:

function total(fn){
	// 调用total时传入了目标处理函数fn,最终是要获取到这个函数处理的结果
	// 传入了需要处理的第一个参数 100
	let args = Array.prototype.slice.call(arguments,1);
	// 返回了一个新的函数,并等待调用
	return function(){
		// 获取到了剩余的参数
		let nextArgs = Array.prototype.slice.call(arguments);
		let allArgs = args.concat(nextArgs);
		// 调用目标函数 fn  ,并返回结果
		return fn.apply(null,allArgs);
	}	
}
let first =total(function(){
	console.log(...arguments);
}),100);
first(90);           // 100 90

使用柯里化的特点:

  • 参数复用, 第一次调用total时传入的参数,后续调用新函数一直有效。
  • 提前返回不是很认同,提前返回是惰性函数载入的特点,是为了减少重复代码的执行。
  • 延迟计算,第一次调用后不进行第二次调用不会获得结果。

必须写一下bind()方法的实现:

function bind(fn,context){
	let args = Array.prototype.slice.call(arguments,1);
	return function(){
		let nextArgs = Array.prototype.slice.call(arguments);
		let allArgs = args.concat(nextArgs);
		return fn.apply(context,allArgs);
	}	
}

多了一个context,执行函数fn指定其上下文环境。

参考:
张鑫旭大佬的文章,感谢大佬


函数节流、函数防抖

真的是头大,看的红皮书,里面讲的函数节流实现代码,通过查阅网上资源是函数防抖实现方式

概念理解:

  • 函数节流 ,连续多次调用时,则按照固定频率执行,在固定周期内执行一次
  • 函数防抖,在指定周期内,调用n次执行1次(每次调用会刷新初始执行周期,从头计时)

如果有误,还请指正,谢谢!

  1. 函数防抖
    概念:使一个连续重复执行执行的函数间断执行,使用定时器setTimeout达到目的

    初步感受:

     function print(){
     	console.log("doing...");
     }
     for(let i=0;i<30;i++){
     	print();          // 当然会打印30次  “ding...”
     }
    

    对这个必须说 No,一样的东西为什么我要执行这么多次,我来一个延时^ _^,看你还怎么执行

     let timeId = null;
     function print(){
     	clearTimeout(timeId);
     	timeId = setTimeout(function(){
     		console.log("doing...");
     	},2000);
     }
     // for循环模拟调用
     // for(let i=0;i<30;i++){
     //	 print();      // hahahaha 执行一次  “dong...”
     //}
     // 定时器模拟
     let j=0;
     let intervalId = setInterval(function(){
     	if(j>30){
     		clearInterval(intervalId);
     	}
     	j++;
     	print();   // 打印一次 "doing..."
     },100);
    
  2. 函数节流
    概念:连续多次调用时,则按照固定频率执行,在固定周期内执行一次。

       	function print(fn){
            let timeId = null;
       		return function(){
       			if(!timeId){
       				timeId = setTimeout(function(){
       					timeId = null;
                        console.log("但是我固定频率执行...");
       					fn.apply(null,arguments);
                        console.log("-----------分割线-------------");
       				},2000);
       			}
       		};
       	}
       // 注意这里使用了函数柯里化,
       let obj=  print(function(){
           console.log("haha");
         });
       setInterval(function(){
         	console.log("我在执行...");
        	obj();
       },100);
    

    应用场景:对于较大开销、连续重复执行的事件,比如:onresizeonmousemove等。

纠结了一晚上,也不知道理解的对不对,感觉自己是清楚了。-_-

代码可直接测试执行,查看执行效果

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heroboyluck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值