javascript权威指南-函数-下
作者: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