JS函数式编程读书笔记 - 2

本文章记录本人在进修 函数式 中明白到的一些东西,加深影象和而且整顿记录下来,轻易以后的温习。

函数是一等国民

“一等”这个术语平经常使用来形貌值。当函数被看做“一等国民”时,那它就能够去任何值能够去的处所,很少有限定。比方那数值和函数做比较。

  • 函数与数字一样能够存储为变量

    var fortytwo = function () { return 42; };
    
  • 函数与数字一样能够存储为数组的一个元素。

    var fortytwos = [42, function () { return 42; }];
    
  • 函数与数字一样能够作为对象的成员变量。

    var fortytows = {number: 42, fun: function () {}}
    
  • 函数与数字一样能够在运用的时刻直接竖立出来。

    42 + (function () { return 42; })();
    
  • 函数与数字一样能够被通报给另一个函数。

    function weirdAdd(n, f) { return n + f() };
    
    weirdAdd(42, function() { return 42; });
    
  • 函数与数字一样能够被另一个函数返回。

    return 42;
    
    return function() { return 42; };
    

    关于末了两点,实在就是对“高阶”函数的定义,也就是:

  • 以一个函数作为参数。

  • 返回一个函数作为效果。

从上面举的栗子能够看来。做为“一等国民”的函数就会具有范例数字的性子。

Applicative 编程

简朴来讲Applicative编程定义为函数A作为参数供应给函数B。在Applicative编程三个典范的例子是:maoreducefilter

看下面栗子:

var nums = [1, 2, 3, 4, 5];

// 数组的一切项都 * 2
function doubleAll(array) {
    return _.map(array, function (n) { return * 2 });
}

// 数组的一切项相加,返回 sum / _.size(array)
function average(array) {
    var sum = _.reduce(array, function (a, b) { return a + b });
    return sum / _.size(array);
}

// 塞选数组中的偶数项,而且返回一个新的数组
function onlyEven(array) {
    return _.filter(arr, function (n) {
        return (n % 2) === 0;
    });
}

doubleAll(nums); // [2, 4, 6, 8, 10];
average(nums); // 3
only(nums); / [2,4]

看了上面的栗子,能看出maoreducefilter会在某一个处所终究挪用作为参数的匿名函数。实际上,这些函数的语义能够由这个挪用关联来定义:

  • _.map()遍历集兼并对每一个值挪用一个函数,返回效果的鸠合。
  • _.reduce应用函数将值的鸠合兼并成一个值,该函数接收一个积累和本次处置惩罚的值。
  • _.filter对鸠合每一个值挪用一个谓词函数(也就是返回true或许false的函数),抽取谓词函数返回true的值的鸠合。

鸠合中间编程

函数式编程关于须要操纵鸠合中元素的使命异常有效。新建一个简朴的对象:{a: 1, b: 2},然后拿_.map()运用_.identity()函数(返回其参数的函数)。比方:

_.map({a: 1, b: 2}, _.identity); // [1, 2];

从鸠合为中间的角度看,Underscore和平常函数式编程所首倡的是要竖立一个一致的处置惩罚体式格局,使我们能够重用一套综合的函数。

用 100 个函数操纵一个数据结构,必用 10 个函数操纵 10 个数据结构要好。

定义几个 Applicative 函数

Underscore供应了很多的applicative函数,有兴致的能够去浏览一下API以及源码。通太小栗子来看看怎样竖立一个applicative函数:

// 一个简朴、接收肯定数目标参数并衔接它们的函数并非 applicative。

function cat() {
    var head = _.frist(arguments);
    if (existy(head))
        return head.concat.apply(head, _.reset(arguments));
    else
        return [];
}

cat([1, 2, 3], [4, 5], [6, 7, 8]); // [1, 2, 3, 4, 5, 6, 7, 8]

接着继承定义一个construct函数,construct函数接收一个元素和一个数组,而且cat将元素防备在数组火线:

function construct(head, tail) {
    return cat([head], _.toArray(tail)));
}
construct(42, [1, 2, 3]); // [42, 1, 2, 3]

虽然上面的construct函数中运用到了cat,然则它并没有将cat作为参数传入,所以不符合请求。

在定义一个函数mapcat

function mapcat(fun, coll) {
    return cat.apply(null, _.map(coll, fun);
}

mapcat(function (e) {
    return construct(e, [","]);
}, [1,2,3]); // [1, ",", 2, ",", 3, ","]

mapcat函数接收一个函数fun,与_.map用了雷同的体式格局,对给定鸠合中的每一个元素举行挪用。这类fun的运用是mapcatapplicative实质。

当映射函数返回一个数组,mapcat能够将其展平。接着继承定义butLastinterpose函数:

function butLast(coll) {
    return _.toArray(coll).slice(0, -1);
}

function interpose(inter, coll) {
    return butLast(mapcat(function (e) {
        return construct(e, [inter]);
    }, coll));
}

interpose(",", [1, 2, 3]); // [1, ",", 2, ",", 3]

用较低级别的函数来逐渐定义和运用离散功用。

数据思索

js中,对象范例是异常壮大的,但与其一同事情的东西并不完全是函数式的。相反,用js对象更经常使用的形式是,以多态调理为目标来附加要领。

虽然把js对象当做数据映射来操纵和接见的东西自身很少,然则幸好有Underscore供应了有效的一系列操纵。其中有:_.keys_.values_.pluck。有兴致的能够去看看API文档。

_.pluck函数和_.omit函数做一个小栗子:

var person = {name: "Romy", token: "j3983ij", password: "trigress"};

var info = _.omit(person, 'token', 'password'); // {name: "Romy"}

var creds = _.pick(person, 'token', 'password'); // {token: "j3983ij", password: "trigress"}

上面的栗子是,运用雷同的“风险”键:tokenpassword_.onmit函数接收一个黑名单,从对象中删除键,而_.pick依据白名单保存响应键,且都不会修正本来的对象。

假如运用过了Underscore函数来操纵对象,你会以为异常相似与SQL,都是依据一个壮大的声明规约举行过滤和处置惩罚逻辑数据表。

总结

末了总结一下一等函数:

  • 它们能够存储在变量中。
  • 它们能够被存储在数组中的插槽中。
  • 它们能够存储在对象的字段中。
  • 它们能够依据需求来竖立。
  • 它们能够被通报到其他函数中。
  • 它们能够被其他函数返回。

一等函数的意义就是以上的几点了。能够简朴它具有数值一样的性子。

在总结一下applicative编程,简朴来讲就是函数A作为参数供应给函数B_.map_.reduce_.filter就是最好的例子。

有啥不对,请指正!

    原文作者:_我已经从中二毕业了
    原文地址: https://segmentfault.com/a/1190000003088491
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞