zoukankan      html  css  js  c++  java
  • 函数柯里化

    函数柯里化(function currying):是把接收多个参数的函数变换成接收一个单一参数(最初函数的第一个参数)的函数,并且返回接收余下的参数而且返回结果的新函数的技术。

    解释有些抽象,先来看下面的例子:

     1 //普通函数
     2 function add(num1, num2) {
     3     return num1 + num2;
     4 }
     5 
     6 //柯里化后
     7 function curriedAdd(num1) {
     8     return function(num2) {
     9         return num1 + num2;
    10     }
    11 }
    12 
    13 alert(add(2, 3);  //5
    14 alert(curriedAdd(3)(5)); //8

    实际上,就是把add函数的num1,num2两个参数变成了先用一个函数接收num1参数然后返回一个函数去处理num2参数。

    函数柯里化的用处:

    1.参数复用

     1 function check(reg, str) {
     2     return reg.test(str);
     3 }
     4 
     5 check(/d+/g, 'test');   //false
     6 check(/[a-z]+/g, 'test'); //true
     7 
     8 function curryingCheck(reg) {
     9     return function(str) {
    10         return reg.test(str);
    11     }
    12 }
    13 
    14 var hasNumber = curryingCheck(/d+/g);
    15 
    16 hasNumber('test1');   //true
    17 hasNumber('testtest');  // false
    18 hasNumber('abc');  //false

     上面的示例,就是对check()函数第一个参数reg进行了复用。

    2.提前确认

     1 var addEvent = function(element, event, handler) {
     2     if(document.addEventListener) {
     3         if(element && event && handler) {
     4             element.addEventListener(event, handler, false);
     5         }
     6     } else {
     7         if(element && event && handler) {
     8             element.attachEvent('on' + event, handler);
     9         }
    10     }
    11 }
    12 
    13 
    14 var addEvent = (function() {
    15     if(document.addEventListener) {
    16         return function(element, event, handler) {
    17             if(element && event && handler) {
    18                 element.addEventListener(event, handler, false);
    19             }
    20         };
    21     } else {
    22         return function(element, event, handler) {
    23             if(element && event && handler) {
    24                 element.attachEvent('on' + event, handler);
    25             }
    26         };
    27     }
    28 })();

    调用函数执行一次判断后返回一个函数,之后同一个用户就不用再进行判断了。

    3.延迟运行

    1 Function.prototype.bind = function(context) {
    2     var _this = this;   
    3     var args = Array.prototype.slice.call(arguments, 1);
    4 
    5     return function() {
    6         return _this.apply(context, args);
    7     }
    8 }

    我们在JavaScript中经常使用的bind()方法,实现的机制就是currying。

    柯里化函数通常由以下步骤动态创建:调用另一个函数并为它传入要柯里化的函数和必要参数。下面是创建柯里化函数的通用方式:

    1 function curry(fn) {
    2     var args = Array.prototype.slice.call(arguments, 1);
    3     
    4     return function() {
    5         var innerArgs = Array.prototype.slice.call(arguments);
    6         var finalArgs = args.concat(innerArgs);
    7         return fn.apply(null, finalArgs);
    8     }
    9 }

     实现一个curry()函数, 将普通函数柯里化

     1 function curry(fn, args=[]) {
     2     return function() {
     3         let rest = [...args, ...arguments];
     4         if(rest.length < fn.length) {
     5             return curry.call(this, fn, rest);
     6         } else {
     7             return fn.apply(this, rest);
     8         }
     9     }
    10 }
    11 
    12 function add(x, y, z) {
    13     return a + b + c;
    14 }
    15 
    16 let sum = curry(add);
    17 console.log(sum(1)(2)(3));   //6
    18 console.log(sum(1)(2, 3));   //6

    函数柯里化的性能问题:

    1. 存取arguments对象通常要比存取命名参数要慢一点
    2. 一些老版本的浏览器在arguments.length的实现上是相当慢的
    3. 使用fn.apply()和fn.call()通常比直接调用fn()稍微慢点
    4. 创建大量嵌套作用域和闭包函数会带来开销,无论是在内存上还是速度上。

    一道经典面试题

     1 //实现一个add方法,使计算结果能够满足如下预期:
     2 
     3 add(1)(2)(3) = 6;
     4 add(1, 2, 3)(4) = 10;
     5 add(1)(2)(3)(4)(5) = 15;
     6 
     7 function add() {
     8     var _args = Array.prototype.slice.call(arguments);
     9 
    10     var _adder = function() {
    11         _args.push(...arguments);
    12         return  _adder;
    13     };
    14     
    15     _adder.toString = function() {
    16         return _args.reduce(function(a, b) {
    17             return a + b;
    18         });
    19     }
    20     return _adder;
    21 }
    22 
    23 add(1)(2)(3)    //6
    24 add(1, 2, 3)(4)  //10
    25 add(1)(2)(3)(4)(5)   //15
    26 add(2, 6)(1)  //9

    参考链接:详解JS函数柯里化

     

     

  • 相关阅读:
    unable to start kestrel System.Net.Sockets.SocketException (10013): 以一种访问权限不允许的方式做了一个访问套接字的尝试。
    c# 复制文件夹内所有文件到另外一个文件夹
    git初始化
    c# 递归获取所有目录,所有文件,并替换文件
    新增项目 提交到gitee
    netcore3.1 跨域请求
    netcore appsettings.json 绑定对象
    nuget安装包
    做人六字诀:静,缓,忍,让,淡,平
    docker安装部署
  • 原文地址:https://www.cnblogs.com/sparkler/p/13719122.html
Copyright © 2011-2022 走看看