js 函数式编程学习笔记

(1)平常写的函数大多是接受值,合并值,返回值,比如经常写的for循环:

function printArray(array){
  for(var i=0;i<array.length;i++){
     print(array[i]);
  }
}

但是如果我们想做print之外的事情呢?怎么办?再写一个相似的,未免显得浪费,我们可以这样

function forEach(array,action){
  for(var i=0;i<array.length;i++){
    action(array[i]);
  }
}
forEach(["a","b","c"],print);

通过利用匿名函数,在编写for循环之类的可以省去很多无用的细节:

function sum(numbers){
  var total = 0;
  forEach(numbers,function(number){
     total+=number;
  })
  return total;
}

上面的例子中是“遍历数组”,并使其抽象化,函数作为函数参数传入....

(2)另一种是传入函数参数,返回函数,可以在“高阶函数”中传入arguments

function negate(func){
  return function(x){
    return !func(x);
  }
}
var isNotNaN = negate(isNaN);
isNotNaN(NaN);

如果想要反转的函数接受参数大于1个,怎么办?? 很简单,借助apply方法,上下文传入NULL

传说中的组合模式:
function compose(f1,f2){
   return function(){
      return f1(f2.apply(null,arguments));
   };
}

var isNotNaN = compose(op["!"],isNaN);
isNotNaN(5); =>true

间接函数调用,如果运行次数较多还是不要用的好..

(3)sum函数实际上是算法的一个变体,该算法通常称为规约

function reduce(combine,base,array){
  forEach(array,function(element){
    base = combine(base,element);
  });
}

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

reduce(add,0,array);

(4)另外一个与数组相关的有用的基本算法称为“映射”。它能够遍历数组

function map(func,array){
  var result = [];
  forEach(array,function(element){
    result.push(func(element));
  });
  return result;
}

map(Math.round,[0.01,2,9,Math.PI]);

(5)下面这段代码,可以研究下它的工作原理

function splitParagraph(text){
  function split(pos){
     if(pos == text.length) return [];
     else if(text.charAt(pos) == "*"){
         var end = findClosing(“*”,pos+1);
         frag = {type:“emphasized”,content:text.slice(pos+1,end)};
         return [frag].concat(split(end+1));  //回调
     } else if(text.charAt(pos) == "{"){
         var end = findClosing(“{”,pos+1);
         frag = {type:“emphasized”,content:text.slice(pos+1,end)};
         return [frag].concat(split(end+1));  //回调
     } else{
        var end = findOpeningOrEnd(pos),
           frag = {type:"normal",content:text.splice(pos+1,end)};
           return [frag].concat(split(end));

     }
  }
  function findClosing(character,from){
     var end = text.indexOf(character,from);
     if(end == -1) throw new Error("Missing closing ' "+character+"'");
     return end;
  }
  function findOpeningOrEnd(from){
     function indexOrEnd(character){
        var index = text.indexOf(character,from);
        return index = -1?text.length:index;
     }
     return Math.min(indexOrEnd("*"),indexOrEnd("{"));
  }

  return split(0);
}

这种函数的编程风格很独特,使用递归而不是循环,其实递归效率是比较低的,改进如下:

function split(){
   var pos = 0,fragments = [];
   while(pop<text.lenght){
      if(text.charAt(pos) == "*"){
         var end = findClosing("*",pos+1);
         fragments.push({type:"emphasized",content:text.slice(pos+1,end)});
         pos = end+1;
      }else if(text.charAt(pos) == "{"){
         var end = findClosing("}",pos+1);
         fragments.push({type:"footnote",content:text.slice(pos+1,end)});
      }
      else{
         var end = findOpeningOrEnd(pos);
         fragments.push({type:“footnote”,content:text.slice(pos,end)});
         pos = end;
      }

   }
   return fragments;
}

(6)分布应用模式

function partial(func){
   var knownArgs = arguments;
   return function(){
      var realArgs = [];
      for(var i=1;i<knownArgs.length;i++){ //from 1
        realArgs.push(knowArgs[i]);
      }
      for(var i=0;i<arguments.length;i++){
        realArgs.push(arguments[i]);
      }
      return func.apply(null,realArgs);
   }
}

map(partial(op["+"],1),[0,2,4,6,8,10]); // op["+"] swithcase 的一个function
(0)

相关推荐

  • JavaScript装饰器函数(Decorator)实例详解

    本文实例讲述了JavaScript装饰器函数(Decorator).分享给大家供大家参考,具体如下: 装饰器函数(Decorator)用于给对象在运行期间动态的增加某个功能,职责等.相较通过继承的方式来扩充对象的功能,装饰器显得更加灵活,首先,我们可以动态给对象选定某个装饰器,而不用hardcore继承对象来实现某个功能点.其次:继承的方式可能会导致子类繁多,仅仅为了增加某一个单一的功能点,显得有些多余了. 下面给出几个常用的装饰器函数示例,相关代码请查看github. 1 动态添加onload

  • Javascript闭包与函数柯里化浅析

    闭包和柯里化都是JavaScript经常用到而且比较高级的技巧,所有的函数式编程语言都支持这两个概念,因此,我们想要充分发挥出JavaScript中的函数式编程特征,就需要深入的了解这两个概念,闭包事实上更是柯里化所不可缺少的基础. 一.柯里化的概念 在计算机科学中,柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由Christopher Strachey以逻辑学家 Haskell Curry 命名的,尽管

  • javascript中利用柯里化函数实现bind方法【推荐】

    • 柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: • 柯里化函数主要起到预处理的作用: • bind方法的作用:把传递进来的callback回调方法中的this预先处理为上下文context; /** * bind方法实现原理1 * @param callback [Function] 回调函数 * @par

  • 深入解析JavaScript中函数的Currying柯里化

    引子 先来看一道小问题: 有人在群里出了到一道题目: var s = sum(1)(2)(3) ....... 最后 alert(s) 出来是6  var s = sum(1)(2)(3)(4) ....... 最后 alert(s) 出来是10  问sum怎么实现? 刚看到题目,我第一反应是sum返回的是一个function,但是没有最终实现,印象中看到过类似的原理,但是记不清了.   后来同事说,这个是叫柯里化, 实现方法比较巧妙: function sum(x){ var y = func

  • 深入学习 JavaScript中的函数调用

    定义 可能很多人在学习 JavaScript 过程中碰到过函数参数传递方式的迷惑,本着深入的精神,我想再源码中寻找些答案不过在做这件事之前,首先明确几个概念.抛弃掉值传递.引用传递等固有叫法,回归英文: call by reference && call by value && call by sharing 分别是我们理解的 C++ 中的引用传递,值传递.第三种比较迷惑,官方解释是 receives the copy of the reference to object

  • js function定义函数使用心得

    1.最基本的作为一个本本分分的函数声明使用. 复制代码 代码如下: function func(){} 或 var func=function(){}; 2.作为一个类构造器使用: 复制代码 代码如下: function class(){} class.prototype={}; var item=new class(); 3.作为闭包使用: 复制代码 代码如下: (function(){ //独立作用域 })(); 4.可以作为选择器使用: 复制代码 代码如下: var addEvent=ne

  • 浅谈JS中的bind方法与函数柯里化

    绑定函数bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值.不同于call和apply只是单纯地设置this的值后传参,它还会将所有传入bind()方法中的实参(第一个参数之后的参数)与this一起绑定. 关于这个特性看<JS权威指南>原文的例子: var sum = function(x,y) { return x + y }; var succ = sum.bind(null, 1); //让this指向null,其后的实参也会作为实参传入被绑定的函数sum

  • javascript中有趣的反柯里化深入分析

    写在前面的话:国内对前端的研究在某些方面也不逊色于国外,这篇文章虽然看不太懂,但我很欣赏这种深入研究的精神! 反科里化的话题来自javascript之父Brendan Eich去年的一段twitter. 近几天研究了一下,觉得这个东东非常有意思,分享一下.先忘记它的名字,看下它能做什么. 不要小看这个功能,试想下,我们在写一个库的时候,时常会写这样的代码,拿webQQ的Jx库举例. 我们想要的,其实只是借用Array原型链上的一些函数.并没有必要去显式的构造一个新的函数来改变它们的参数并且重新运

  • 深入剖析JavaScript中的函数currying柯里化

    curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名).   柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程. 柯里化一个求和函数 按照分步求值,我们看一个简单的例子 var concat3Words = function (a, b, c) { r

  • JavaScript函数柯里化详解

    什么是柯里化 柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数(译注:最初函数的第一个参数)的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数. 柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用: bind方法的作用:把传递进来的callba

  • JavaScript函数柯里化原理与用法分析

    本文实例讲述了JavaScript函数柯里化原理与用法.分享给大家供大家参考,具体如下: 柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数(译注:最初函数的第一个参数)的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数. 也就是说是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数. 例如,我想创建一个做自我介绍的函数,每个人只要输入自己姓名.性别.年龄即可.但是当A使用这个函数时,每次调用,都必

  • javascript中利用柯里化函数实现bind方法

    柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预先存储的值进行相关的操作处理即可: 柯里化函数主要起到预处理的作用: bind方法的作用:把传递进来的callback回调方法中的this预先处理为上下文context; /** * bind方法实现原理1 * @param callback [Function] 回调函数 * @param con

  • js中匿名函数的N种写法

    匿名函数没有实际名字,也没有指针,怎么执行滴? 其实大家可以看看小括号的意义就应该可以理解.小括号有返回值,也就是小括号内的函数或者表达式的返回值,所以说小括号内的function返回值等于小括号的返回值,不难理解 (function(){})()可以将没有名字的函数执行了把- 关于匿名函数写法,很发散~ 最常见的用法: 复制代码 代码如下: (function() { alert('water'); })(); 当然也可以带参数: 复制代码 代码如下: (function(o) { alert

随机推荐