作者:gcbeen

日期:2013年10月26日

一、使用函数处理数组

    // 非函数式编程
    var data = [1, 1, 3, 5, 5],
        len = data.length,
        total = 0,
        mean,
        deviation,
        stddev,
        i;
    for (i = 0; i < len; i += 1) {
      total += data[i];
    }
    mean = total / len;
    
    total = 0;
    for (i = 0; i < len; i += 1) {
      deviation = data[i] - mean;
      total += deviation * deviation;
    }
    stddev = Math.sqrt(total / (len - 1) );
    // 函数式编程
    var sum = function (x, y) {
      retur x + y;
    };
    var square = function (x) {
      return x * x;
    };
    var data = [1, 1, 3, 5, 5];
    var mean = data.reduce(sum) / data.length;
    var deviations = data.map(function (x) { return x - mean; } );
    var stddev = Math.sqrt(deviations.map(square).reduce(sum) / (data.length - 1) );
    // 基于ECMAScript 3的函数式编程。
    var map = Array.prototype.map ? function (a, f) { return a.map(f); } : implementMap;

    function implementMap(a, f) {
      var results = [],
          i,
          len = a.length;
      for (i = 0; i < len; i += 1) {
        if (i in a) {
          results[i] = f.call(null, a[i], i, a);
        }
      }
      return results;
    }
    var reduce = Array.prototype.reduce ? function (a, f, initial) {
      if (arguments.length > 2) {
        return a.reduce(f, initial);
      } else {
        return a.reduce(f);
      }
    } : implementReduce;

    function implementReduce(a, f, initial) {
      var i = 0,
          len = a.length,
          accumulator;
      if (arguments.length > 2) {
        accumulator = initial;
      } else {
        if (len == 0) {
          throw TypeError();
        }
        for (i = 0; i < len; i += 1) {
          if (i in a) {
            accumulator = a[i];
            break;
          }
        }
        if (i == len) {
          throw TypeError();
        }
      }
    
      while (i < len) {
        if (i in a) {
          accumulator = f.call(undefined, accumulator, a[i], i, a);
        }
        i += 1;
      }
      return accumulator;
    };
    
    var data = [1, 1, 3, 5, 5];
    var len = data.length;
    var sum = function (x, y) { return x + y; };
    var square = function (x) { return x * x; };
    var mean = reduce(data, sum)/ len;
    var deviations = map(data, function (x) { return x - mean; });
    var stddev = Math.sqrt(reduce(map(deviations, square), sum) / (len - 1));

二、高阶函数

高阶函数就是操作函数的函数。

    function not(f) {
      return function () {
        var result = f.apply(this, arguments);
        return !result;
      };
    }
    
    var even = function (x) {
      return x % 2 === 0;
    }
    var odd = not(even);
    [1, 2, 3, 5, 5].every(odd);
    function mapper(f) {
      return function (a) {
          return map(a, f);
      };
    }
    var increment = function (x) {
        return x + 1;
    };
    var incrementer = mapper(increment);
    incrementer([1, 2, 3]);
    function compose(f, g) {
      return f.call(this, g.apply(this, arguments) );
    }
    var square = function (x) { return x * x; };
    var sum = function (x, y) { return x + y; };
    var squareofsum = compose(square, sum);
    squareofsum(2, 3);

三、不完全函数


    function array(a, n) {
      return Array.prototype.slice.call(a, n || 0);
    }
    
    // 将函数的实参传递至左侧。
    function partialLeft(f /* ,.... */) {
      var args = arguments;
      return function () {
        var a = array(args, 1);
        a = a.concat(array(arguments) );
        return f.apply(this, a);
      };
    }
    
    // 将函数的实参传递至右侧。
    function partialRight(f /*, ... */) {
      var args = arguments;
      return function () {
        var a = array(arguments);
        a = a.concat(array(args, 1) );
        return f.apply(this, a);
      };
    }
    
    function partial(f /*, ... */) {
      var args = arguments;
      return function () {
        var a = array(args, 1);
        var i = 0, j = 0;
        for (; i < a.length; i += 1) {
          if (a[i] == undefined) {
            a[i] = arguments[j];
            j += 1;
          }
        }
        a = a.concat(array(arguments, j) );
        return f.apply(this, a);
      };
    }
    
    var f = function (x, y, z) {
      return x * (y -z);
    }
    
    partialLeft(f, 2)(3, 4);
    partialRight(f, 2)(3, 4);
    partial(f, undefined, 2)(3, 4);

    
    var increment = partialLeft(sum, 1);
    var cuberoot = partialRight(Math.pow, 1/3);
    String.prototype.first = partial(String.prototype.charAt, 0);
    String.prototype.last = partial(String.prototype.substr, -1, 1);
    
    
    function compose(f, g) {
      return function () {
        return f.call(this, g.apply(this, arguments) );
      };
    }
    
    var not = partialLeft(compose, function (x) { return !x; });
    var even = function (x) {
      return x % 2 === 0;
    };
    var odd = not(even);
    var isNumber = not(isNaN);
    
    var data = [1, 1, 3, 5, 5];
    var sum = function (x, y) { return x + y; };
    var product = function (x, y) { return x * y; };
    var neg = partial(product, -1);
    var square = partial(Math.pow, undefined, 2);
    var sqrt = partial(Math.pow, undefined, 0.5);
    var reciprocal = partial(Math.pow, undefined, -1);
    
    var mean = product(reduce(data, sum), reciprocal(data.length) );
    
    /*
    var stddev = sqrt(product( 
                reduce(map(data, compose(square, partial(sum, neg(mean)))), sum),
                reciprocal(sum(data.length, -1))
                ));
    */

    var composeFunc = compose(square, partial(sum, neg(mean) ) );
    var product1 = reduce(map(data, composeFunc ), sum );
    var product2 = reciprocal(sum(data.length, -1) );
    var stddev = sqrt(product(product1, product2));

四、记忆

    // 返回带有记忆功能的函数
    function memorize(f) {
      var cache = {};
      return function () {
        var key = arguments.length + Array.prototype.join.call(arguments, ",");
          return cache[key] || cache[key] = f.apply(this, arguments);
      };
    }
    
    
    function gcd(a, b) {
      var t;
      if (a < b) {
        t = b, b = a, a  = t;
      }
      while (b != 0) {
        t = b, b = a % b, a = t;
      }
      return a;
    }
    
    var gcdmemo = memorize(gcd);
    gcdmemo(85, 187);
    
    // 有记忆功能的递归函数
    var factorial = memorize( function (n) { return (n <= 1) ? 1 : n * factorial(n-1); });
    factorial(5);
    


blog comments powered by Disqus