函数柯里化 curry

一、函数柯里化的特性:

(1)参数复用 $.ajax

// 示例一
function ajax(type,url,data) {
  var xhr = new XMLHttpRequest();
  xhr.open(type,url,true);
  xhr.send(data);
}

var ajaxCurry = curry(ajax);
// 以GET请求为例
GET('www.baidu.com','name=Derry');

// 示例二
function add(a,b,c){
  return a + b + c;
}

const curryAdd = function(a){
  return function(b){
    return function(c){
      return a + b + c;
    }
  }
}

console.log(add(5,10,15)); // 结果30

const add5 = curryAdd(5); // 固定第一个参数。让表达式已经具有了一个参数5,向外暴露add5

console.log(add5(10)(15)); // 30

(2)提前返回 onclick... addEventListener()

// 示例一
var addEvent = function(el, type, fn, capture){
  if(window.addEventListener){
    el.addEventListener(type,function(e){
      fn.call(el,e);
    },capture);
  }else if(window.attachEvent){ // 兼容6.7.8
    el.attachEvent('on' + type,function(e){
      fn.call(el,e);
    })
  }
}

addEvent(a,'click',handleClick,true);
addEvent(a,'click',handleClick,true);
addEvent(a,'click',handleClick,true);

// 示例二(优化版)
var addEvent = (function(){
  if(window.addEventListener){
    return function(el, type, fn, capture){
      el.addEventListener(type,function(e){
        fn.call(el,e);
      },capture);
    }
  }else if(window.attachEvent){ // 兼容6.7.8
    return function(el, type, fn, capture){
      el.attachEvent('on' + type,function(e){
        fn.call(el,e);
      })
    }
  }
})() // 自运行函数(闭包)

(3)延迟执行 -> 不定参数

// 使用柯里化可以将函数的参数积累起来到某个触发点时再进行参数的执行
var totalScore = 0;
// 柯里化
var curryScore = function(fn){
  var _totalScore = [];
  return function(){
    if(arguments.length === 0){
      return fn.apply(null, _totalScore);
    }else{
      _totalScore = _totalScore.concat([].slice.call(arguments));
    }
  }
}

var curryAddScore = curryScore(function(){
  var i=0;len = arguments.length;
  for(i;i<len;i++){
    totalScore += arguments[i]
  }
});

curryAddScore(3);
console.log(totalScore); // 0
curryAddScore(2);
console.log(totalScore); // 0
curryAddScore(1);
curryAddScore(1);
console.log(totalScore); // 0
curryAddScore(3);
curryAddScore(); // 参数为0的时候,才触发业务逻辑代码
console.log(totalScore); // 10

二、总结

// 柯里化封装
function curry(fn,args){
  // 需要得到或者说判断 fn到底有几个参数 -- fn.length
  var length = fn.length; // length 起到了延迟执行的触发判断条件
  args = args || []; // args 参数复用
  return function(){
    var _args = args.slice(0), arg, i;
    for(i=0; i<arguments.length; i++){
      arg = arguments[i];
      _args.push(arg);
    }
    if(_args.length < length){
      return curry.call(this, fn, _args);
    }else{
      return fn.apply(this, _args);
    }
  }
}

function add(a,b,c){
  return a + b + c;
}

var curryAdd = curry(add);
console.log(curryAdd(5)(10)(15)); // 30
console.log(curryAdd(5,10)(15)); // 30
console.log(curryAdd(5,10,15)); // 30
var curryAdd5 = curryAdd(5);
console.log(curryAdd5(10,15)); // 30

.

posted @ 2018-06-16 22:33  每天都要进步一点点  阅读(174)  评论(0编辑  收藏  举报