Application of higher order functions

Functions are passed as arguments

  • The callback function
let getUserInfo = function ( userId, callback ) {
	$ajax('http://xxx.com/getUserInfo?id=userId', function (data){
  		if(typeof callback==='function'){
        	callback(data)
        }  
    })
}
Copy the code
  • Array.prototype.sort

    [1,4,3]sort(function (a, b) {return a - b; }); [1,4,3]sort(function (a, b) {return b-a; }); // output [4,3,1]Copy the code

    Function is output as the return value

  • Determine the type of data

     let Type = {};
     for (let i = 0, type; (type = ["String", "Array", "Number"][i++]); ) {
       (function (type) {
         Type["is" + type] = function (obj) {
           return Object.prototype.toString.call(obj) === `[object${type}]`;
         };
       })(type);
     }
     
     Type.isArray([]);
     Type.isString( "S" )
      
    Copy the code
  • getSingle

    Let getSingle = function (fn) {let ret; return function () { return ret || ( ret = fn.apply( this , arguments ) ) }; }; // This function both passes the function as an argument and returns another function after it executes. Let getScript = getSingle(function(){return document.createlement ('script'); }); let script1 = getScript(); let script2 = getScript(); alert(script1 === script2); / / output trueCopy the code

Higher-order functions implement AOP

The main role of AOP is to isolate functions that are not related to the core business logic module, such as logging statistics, security control, exception handling, and so on. These functions are extracted and incorporated into the business logic through “dynamic weaving”. The benefits of doing this are first to keep the business logic modules clean and cohesive, and second to make it easy to reuse functional modules such as log statistics.

Implementing AOP in JavaScript involves “dynamically weaving” one function into another, and there are many specific techniques. This example does this by extending function.prototype.

Function.prototype.before = function( beforefn ){ var __self = this; Beforefn.apply (this, arguments); 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(); // Output result // 1/2/3Copy the code

Other applications of higher order functions

  • curring

Curring is also called partial evaluation. A curring function first takes some arguments, which are not evaluated immediately, and then continues to return another function. The arguments passed are stored in the closure formed by the function. When the function is actually asked for a value, all the arguments passed in before are used to evaluate it at once. Example:

Var monthlyCost = 0; var cost = function( money ){ monthlyCost += money; }; cost( 100 ); // Day 1 cost cost(200); // Day 2 cost cost(300); // Day 3 cost //cost(700); // Day 30 overhead alert (monthlyCost); // Output: 600Copy the code

We can see how much we spent each day, but our goal is to see how much we spent at the end of the month, so we only need to calculate it once at the end of the month.

var cost = (function(){ var args = []; return function(){ if ( arguments.length === 0 ){ var money = 0; for ( var i = 0, l = args.length; i < l; i++ ){ money += args[ i ]; } return money; }else{ [].push.apply( args, arguments ); }}}) (); cost( 100 ); // Cost (200) is not evaluated; // Cost (300); // Console.log (cost()) is not evaluated; // Evaluate and print: 600Copy the code

But that’s not the full Curring. Next we write a generic function curring(){} that takes one argument, the function to be curring. In this case, the function is going to go through the expenses for each day of the month and figure out their sum. The code is as follows:

var currying = function( fn ){ var args = []; return function(){ if ( arguments.length === 0 ){ return fn.apply( this, args ); }else{ [].push.apply( args, arguments ); return arguments.callee; }}}; 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 = currying( cost ); // Convert this function to cost(100); // Cost (200) is not evaluated; // Cost (300); // not really evaluated alert (cost()); // Evaluate and print: 600Copy the code
  • Function of the throttle

How it works: Delay the execution of a function with setTimeout. If the delay is not complete, subsequent calls to the function are ignored. The throttle function takes two parameters, the first being the function to be delayed and the second being the time to delay execution. Specific code:

Var throttle = function (fn, interval) {var throttle = function (fn, interval) {var throttle = function (fn, interval); Return function () {var args = arguments, __me = this; If (firstTime) {// If it is the first call, there is no delay in executing __self.apply(__me, args); return firstTime = false; } if (timer) {// If the timer is still running, the last delay has not completed. Return false; Timer = setTimeout(function () {// Delay the execution of clearTimeout(timer); timer = null; __self.apply(__me, args); }, interval || 500 ); }; }; window.onresize = throttle(function(){ console.log( 1 ); }, 500);Copy the code