Other applications for higher-order functions 1.currying
Function Curry, also known as partial evaluation, a currying function will first accept a number of parameters, after accepting these parameters, the function will not immediately evaluate, but continue to return to another function, just passed the parameter in the function formed in the closure of the saved up. Until the function is truly evaluated, all previously passed parameters are evaluated once.
varCost = (function(){ varargs = []; return function(){ if(Arguments.length = = 0 ){ varMoney = 0; for(vari = 0, L = args.length; I < L; i++) { money+=args[i]; } returnMoney ; }Else{[].push.apply (args, arguments); } }})(); Cost (100);//not really evaluatedCost (200);//not really evaluatedCost (300);//not really evaluatedConsole.log (Cost ());//Evaluation and output:
No parameter evaluation with parameter not value
varcurrying =function(FN) {varargs = []; return function(){ if(Arguments.length = = 0 ){ returnFn.apply ( This, args); }Else{[].push.apply (args, arguments); //Arguments.callee in which function, it represents which function, mainly used in the anonymous function returnArguments.callee; } } }; varCost = (function(){ varMoney = 0; return function(){ for(vari = 0, L = arguments.length; I < L; i++) { money+=arguments[i]; } returnMoney ; } })(); varCost = currying (cost);//The cost function transformed into currying function has the centralized processing of parametersCost (100);//not really evaluatedCost (200);//not really evaluatedCost (300);//not really evaluatedAlert (Cost ());//Evaluation and output:
The second example is more general, pulling the process out of the curry.
2.uncurrying
The process of curry is to gradually pass the parameters, gradually reduce the applicable scope of the function, and gradually solve the process. The function of the anti-curry function in relation to the expansion functions can be used by arbitrary objects to make functions that would otherwise be possessed by a particular object.
Obj.func (Arg1, arg2) =====> func (obj, arg1, arg2)
Dynamic languages are easier to achieve, and here's one way to do it:
varuncurrying=function(FN) {return function () { varArgs=[].slice.call (arguments,1); returnFn.apply (arguments[0],args); } }; varTest= "A,b,c"; varsplit_new=uncurrying (String.prototype.split); Test.split (",");//["A", "B", "C"]Split_new (Test, ', ');//["A", "B", "C"]
3. Function throttling
Reduce unnecessary function autonomy calls, such as Window.onresize event MouseMove drag events
One of the implementation methods:
The function that is about to be executed is deferred for a period of time with settimeout. If the deferred execution is not completed, then the request to invoke the function is ignored. The function accepts 2 parameters, the first parameter is a function that needs to be deferred, and the second parameter is the time that the delay is executed.
varThrottle =function(FN, interval) {var__self = FN,//Save a function reference that needs to be deferredTimer//TimerFirsttime =true;//is it the first time that you call return function () { varargs =arguments, __me= This; if(Firsttime) {//If this is the first call, there is no need to delay execution__self.apply (__me, args); returnFirsttime =false; } if(timer) {//If the timer is still in, the previous deferred execution has not been completed return false; } Timer= SetTimeout (function() {//delay execution for some timecleartimeout (timer); Timer=NULL; __self.apply (__me, args); }, Interval|| 500 ); };}; Window.onresize= Throttle (function() {Console.log (1 );}, 500);
4. Time-sharing function
When the data is too large, such as the friend List has thousands of friends need to render, the browser will only take a breath to render out, which is likely to occupy a lot of performance, causing serious lag. Here can be artificially controlled, the 1000ms rendering 1000 into 200ms rendering 8, batch rendering, reducing pressure
varTimechunk =function(ary, FN, count) {varobj, t; varLen =ary.length; varStart =function(){ for(vari = 0; I < Math.min (Count | | 1, ary.length); i++) {//determine the number of executions and then traverse the execution varobj = Ary.shift ();//Take the first element out of thefn (obj);//Execute function } }; return function() {T= SetInterval (function(){ if(Ary.length = = 0) {//if the array length is 0, this means that the end returnclearinterval (t); } start (); }, 200);//The time interval for batch execution, which can also be passed in as a parameter };};varary = []; for(vari = 1; I <= 1000; i++) {Ary.push (i);}; //here is a random number of data, data total 1000varRenderfriendlist = Timechunk (ary,function(n) {vardiv = document.createelement (' div ' ); Div.innerhtml=N; Document.body.appendChild (div);},8); Renderfriendlist ();
4. Lazy Load function
In web development, some sniffing work is unavoidable because of differences in the implementation between browsers. For example, we need an event binding function addevent that can be generalized in each browser, and the common wording is as follows:
var function (Elem, type, handler) { if (window.addeventlistener) { returnfalse ); } if (window.attachevent) { return elem.attachevent (' on ' + type, handler); }};
The disadvantage of this function is that it executes the IF condition branch inside each time it is called, resulting in unnecessary performance waste.
The second scenario is to advance it to the point where the code is loaded, self-executing, invoking only one judgment, and determining the internal logic beforehand.
var addevent = (function() { if (window.addeventlistener) { return function (Elem, type, handler) { false ); } } if (window.attachevent) { returnfunction(elem, type, handler) { ' on ' + type, handler);}} ) ();
This solution also has a problem, perhaps we will not use the Addevent function, this step is a redundant operation.
The third scheme is the lazy loading function scheme, Addevent is still declared as a normal function, there are still some branch judgment in the function. But after entering the conditional branch for the first time, the function will be overridden inside the function, and the function after the rewrite is the addevent function we expect, and the conditional branching statement no longer exists in the Addevent function when the next time the Addevent function is entered:
1 varAddevent =function(Elem, type, handler) {2 if(window.addeventlistener) {3Addevent =function(Elem, type, handler) {//the difference between this and the previous scenario is that it rewrites itself.4Elem.addeventlistener (type, Handler,false );5 }6}Else if(window.attachevent) {7Addevent =function(Elem, type, handler) {8Elem.attachevent (' on ' +type, handler);9 }Ten } OneAddevent (Elem, type, handler);//This will only be performed the first time, followed by a direct execution of the rewritten A }; - - the vardiv = document.getElementById (' Div1 ' ); - -Addevent (Div, ' click ',function(){ -Alert (1); + }); -Addevent (Div, ' click ',function(){ +Alert (2); A});
Because of the features of JavaScript itself, closures and higher-order functions are very much used, and in JavaScript many design patterns are implemented through closures and higher-order functions. It is important to note that, as opposed to the implementation of the pattern, we are more concerned with what patterns can help us accomplish .
JavaScript Design patterns and development Practices reading notes (3)--Other applications of higher-order functions