1、AOP(面向切面編程)編程
Function.prototype.before=function (beforefn) { var _self=this;//保持原函數的引用 return function () {//返回包含原函數和新函數的「代理」函數 beforefn.apply(this,arguments);//執行新函數,修正this return _self.apply(this,arguments);//執行原函數 } } Function.prototype.after=function (afterfn) { var _self=this; return function () { var ret=_self.apply(this,arguments); afterfn.apply(this,arguments); return ret; } } var func=function () { console.log(2); } func=func.before(function () { console.log(1); }).after(function () { console.log(3) }); func();
2、currying 函數柯里化數組
currying又稱部分求值。過程當中不進行求值進行數值的保持,在最後一步進行求值。app
如:函數
var curring=function (fn) { var args=[]; return function () { if(arguments.length==0){ return fn.apply(this,args); }else{ [].push.apply(args,arguments); return arguments.callee //返回正被執行的 Function 對象 } } } var cost=(function () { var money=0; return function () { for(var i=0,l=arguments.length;i<l;i++){ money+=arguments[i]; } return money; } })(); var cost=curring(cost);//轉換成curring函數 cost(100); cost(200); cost(300); console.log(cost())
輸出結果600,在前3個函數調用的時候把值保持進數組,在最後一步進行數組求和。this
3、uncurringspa
一個對象借用領另外一個對象的方法或屬性prototype
將Array.prototype.push uncurring化代理
Function.prototype.uncurrying=function () { var self=this; return function () { var obj=Array.prototype.shift.call(arguments);//取出arguments第一個值,並將第一個值從arguments中移除 return self.apply(obj,arguments); }; }; var push=Array.prototype.push.uncurrying(); (function () { push(arguments,4); console.log(arguments);//輸出[1,2,3,4] })(1,2,3)
以此類推,其餘Array的方法也能夠uncurringcode
Function.prototype.uncurrying=function () { var self=this; return function () { var obj=Array.prototype.shift.call(arguments);//取出arguments第一個值,並將第一個值從arguments中移除 return self.apply(obj,arguments); }; }; for(var i=0,fn,ary=['push','shift','forEach'];fn=ary[i++];){ Array[fn]=Array.prototype[fn].uncurrying(); }; var obj={ "length":3, "0":1, "1":2, "2":3 }; Array.push(obj,4); console.log(obj.length);//輸出4 var fist=Array.shift(obj); console.log(fist);//輸出1 console.log(obj);//輸出{0:2.1:3,2:4,length:3} Array.forEach(obj,function (i,n) { console.log(n);//分別輸出0,1,2 })
4、函數節流對象
解決頻繁調用問題
var throttle=function (fn,interval) { var _self=fn,//保存須要被延遲執行的函數引用 timer,//定時器 fisrtTime=true;//是否第一次調用 return function () { var args=arguments, _me=this; if(fisrtTime){//若是是第一加載,不須要延時 _self.apply(_me,args); return fisrtTime=false; } if(timer){//若是定時器還在,說明前一次延時執行尚未完成 return false; } timer=setTimeout(function () { clearTimeout(timer); timer=null; _self.apply(_me,args); },interval||500);//||判斷interval是否已定,若是沒有給初始值500 }; }; window.onresize=throttle(function () { console.log(1); },500);
5、分時函數
防止一次性加載過多,進行分時調用。
var timeChunk=function (ary,fn,count) { var obj,t; var len=ary.length; var start=function () { for(var i=0;i<Math.min(count||1,ary.length);i++){ var obj=ary.shift(); fn(obj); } }; return function () { t=setInterval(function () { if(ary.length===0){//若是所有節點都已經建立好 return clearInterval(t); } start(); },200)//分批執行的時間間隔 } } var ary=[]; for(var i=1;i<=1000;i++){ ary.push(i);//假設ary裝載了1000個好友 } var renderFriendList=timeChunk(ary,function (n) { var div=document.createElement('div'); div.innerHTML=n; document.body.appendChild(div); },8); renderFriendList();
6、惰性加載函數
第一次進入分支後重寫函數,第二次不在進行分支判斷
var addEvent=function (elem,type,handler) { if(window.addEventListener){//非IE addEvent=function (elem,type,handler) { elem.addEventListener(type,handler,false); } } else if(window.attachEvent){//非W3C標準,只支持IE addEvent=function (elem,type,handler) { elem.attachEvent('on'+type,handler); } } addEvent(elem,type,handler); }; var div=document.getElementById('div1'); addEvent(div,'click',function () { alert(1); }); addEvent(div,'click',function () { alert(2); });