发表于: 2017-06-03 22:15:45

0 1004


今天做了啥/收获:

终于完成了评审。

看了下函数编程思想:

js 函数式编程

函数式的思想, 就是不断地用已有函数, 来组合出新的函数。

函数式编程具有五个鲜明的特点:

1. 函数是"第一等公民"

指的是函数与其他数据类型一样,处于平等地位

2. 只用"表达式",不用"语句"

"表达式"(expression)是一个单纯的运算过程,总是有返回值;

"语句"(statement)是执行某种操作,没有返回值。

3. 没有"副作用"

指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),

产生运算以外的其他结果。

4. 不修改状态

变量往往用来保存"状态"(state)。不修改变量,意味着状态不能保存在变量中,

函数式编程使用参数保存状态

5. 引用透明

指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,

引用函数所得到的返回值总是相同的

函数式编程的意义:

1. 代码简洁,开发快速

2. 接近自然语言,易于理解

3. 更方便的代码管理

4. 易于"并发编程"

5. 代码的热升级

在 JavaScript 中,函数本身为一种特殊对象,属于顶层对象,

不依赖于任何其他的对象而存在,因此可以将函数作为传出 / 传入参数,

可以存储在变量中,可以做一切其他对象可以做的事情。

自调用函数(递归--自己调用自己)实际上是高阶函数的一种形式。

函数式编程示例:

[javascript] view plain copy

// 阶乘的一般实现  

function factorial(n) {  

  if (n == 1) {  

    return 1;  

  } else {  

    return factorial(n - 1) * n;  

  }  

}  

  

// 阶乘的函数式编程风格实现  

function mul(a, b){  return a*b; }   

function dec(x){  return x - 1; }   

function equal(a, b){  return a==b; }   

  

function factorial(n) {  

  if (equal(n, 1)) {  

    return 1;  

  } else {  

    return mul(n, factorial(dec(n)));  

  }  

}  

函数柯里化:

是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,

并且返回接受余下的参数而且返回结果的新函数的技术。

我的理解就是需要反复调用一个方法a(),它的参数中有一个参数在一定的状况下的值不易改变,

每次调用都写很多次未免太过麻烦,而且也体现不出来它描述和解决的一类问题,这种情况下,

为了避免这两个问题,我们就将其中那个不容易改变的参数给固定下来,新生成一个函数来应对

这一类问题。

加法柯里化的简单实现:

[javascript] view plain copy

//加法  

function adder(num) {  

    return function(x) {  

      return num + x;  

    }  

}  

  

var add5 = adder(5);  

var add6 = adder(6);  

  

console.log(add5(1));// 6  

console.log(add6(1));// 7  

这里的add5表示的函数可以解决基数为5的加法问题,只需要传递一个参数就可以了,

而不必像普通的加法函数那样每次调用都必须添加两个参数。

[javascript] view plain copy

//计算m的n次方  

var powerOfN = function(n){  

    return function(m){  

        var res = 1;  

        for(var i = 0; i < n; ++i){  

            res *= m;  

        }  

        return res;  

    } ;  

};  

//按需生成  

var powerOf2 = powerOfN(2);  

var powerOf3 = powerOfN(3);  

//调用传参  

console.log(powerOf2(3));  

console.log(powerOf3(2));  

柯里化通用实现:

[javascript] view plain copy

function curry(fn) {  

    var args = [].slice.call(arguments, 1);  

    return function() {  

        var inargs = [].slice.call(arguments);  

        console.log(args.concat(inargs));  

        return fn.apply(null, args.concat(inargs));  

    }  

}  

  

function curry(fn) {  

    var args = [].slice.call(arguments, 1);  

    return function() {  

        var inargs = [].slice.call(arguments);  

        console.log(args.concat(inargs));  

        return fn.apply(null, args.concat(inargs));  

    }  

}  

function add(num1, num2) {  

    return num1 + num2;  

}  

var newAdd = curry(add, 5);  

console.log(newAdd(6));  

柯里化将降低了函数使用的普遍性,增加了使用的特异性,使用柯里化需要认真识别

其使用的场景,在符合要求的地方使用,不然会显得啰嗦,降低代码的可读性。

高阶函数

高阶函数即为对函数的进一步抽象,就是以其它函数为输入,或者返回一个函数为输出的函数。

高阶函数最常见的应用如 map(映射), reduce(规约), forEach(遍历), filter(过滤)等,

它们都是以传入不同的函数来以不同的方式操作数组元。

简单应用:

[javascript] view plain copy

function foo(f, g) {  

  return function() {  

    return f.call(null, g.apply(null, arguments));  

    //return f(g.apply(null, arguments)); 也是可以的  

  }  

}  

var sum = function(x, y) {  

  return x + y;  

}  

var square = function(x) {  

  return x * x;  

}  

var squareofsum = foo(square, sum);  

squareofsum(2, 3);// 25  

下面我们来看一下怎样从过程式编程过渡到函数式编程的:

1>形式一

[javascript] view plain copy

var sum = function(x, y) {  

  return x + y;  

}  

var square = function(x) {  

  return x * x;  

}  

function foo(){  

  return square( sum(2, 3) );  

}  

foo();// 25  

2>形式二

[javascript] view plain copy

var sum = function(x, y) {  

  return x + y;  

}  

var square = function(x) {  

  return x * x;  

}  

function foo(f, g){  

  return f( g(2, 3) );  

}  

foo(square, sum);// 25  

3>形式三

[javascript] view plain copy

var sum = function(x, y) {  

  return x + y;  

}  

var square = function(x) {  

  return x * x;  

}  

function foo(f, g){  

  return function(){  

    var num1 = arguments[0];  

    var num2 = arguments[1];  

    console.log(num1, num2);// 2 3  

    var temp = g(num1, num2);  

    console.log(temp);// 5  

    return f(temp);  

  };  

}  

var myfunc = foo(square, sum);  

myfunc(2, 3);// 25  

4>形式四

[javascript] view plain copy

var sum = function(x, y) {  

  return x + y;  

}  

var square = function(x) {  

  return x * x;  

}  

function foo(f, g){  

  return function(){  

    var temp = g.apply(null, arguments);  

    return f(temp);  

  };  

}  

var myfunc = foo(square, sum);  

myfunc(2, 3);// 25  

最后的形式四就是我们想要得到的效果。

其他示例:

1>

[javascript] view plain copy

function foo(fn, array, value){  

  var res = array.map(function(ele){  

    return fn.apply(null, [ele].concat(value));  

  });  

  return res;  

}  

  

function add(x, y) {  

  return x + y;  

}  

  

function sub(x, y) {  

  return x - y;  

}  

  

console.log( foo(add, [1, 2, 3], 3) );// [4, 5, 6]  

console.log( foo(sub, [1, 2, 3], 3) );// [-2, -1, 0]  

2>

[javascript] view plain copy

function multicast(fn) {  

  return function (){  

    var pre = arguments[0];  

    var rest = arguments[1];  

    var ret = pre.map(function(ele) {  

      return fn.apply(this, [ele].concat(rest));  

    });  

    return ret;  

  }  

}  

  

function add(x, y) {  

  return x + y;  

}  

var newAdd = multicast(add);  

console.log(newAdd([1,2,3],3));// [4, 5, 6]  

  

function sub(x, y) {  

  return x - y;  

}  

var newSub = multicast(sub);  

console.log(newSub([1,2,3],3));// [-2, -1, 0]  

明天做啥:拆禅道。 深入了解 开发流程规范


返回列表 返回列表
评论

    分享到