iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >JS组合函数实例分析
  • 277
分享到

JS组合函数实例分析

2023-07-02 09:07:29 277人浏览 泡泡鱼
摘要

本篇内容介绍了“js组合函数实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!组合函数含义函数编程就像拼乐高!乐高有各式各样的零部件,我

本篇内容介绍了“js组合函数实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

组合函数

含义

函数编程就像拼乐高!

乐高有各式各样的零部件,我们将它们组装拼接,拼成一个更大的组件或模型。

函数编程也有各种功能的函数,我们将它们组装拼接,用于实现某个特定的功能。

下面来看一个例子,比如我们要使用这两个函数来分析文本字符串

functioWords(str) {    return String( str )        .toLowerCase()        .split( /\s|\b/ )        .filter( function alpha(v){            return /^[\w]+$/.test( v );        } );}function unique(list) {    var uniqList = [];    for (let i = 0; i < list.length; i++) {        if (uniqList.indexOf( list[i] ) === -1 ) {            uniqList.push( list[i] );        }    }    return uniqList;}var text = "To compose two functions together";var wordsFound = words( text );var wordsUsed = unique( wordsFound );wordsUsed;//  ["to", "compose", "two", "functions", "together"]

不用细看,只用知道:我们先用 words 函数处理了 text,然后用 unique 函数处理了上一处理的结果 wordsFound;

这样的过程就好比生产线上加工商品,流水线加工。

JS组合函数实例分析

想象一下,如果你是工厂老板,还会怎样优化流程、节约成本?

这里作者给了一种解决方式:去掉传送带!

JS组合函数实例分析

即减少中间变量,我们可以这样调用:

var wordsUsed = unique( words( text ) );wordsUsed

确实,少了中间变量,更加清晰,还能再优化吗?

我们还可以进一步把整个处理流程封装到一个函数内:

function uniqueWords(str) {    return unique( words( str ) );}uniqueWords(text)

这样就像是一个黑盒,无需管里面的流程,只用知道这个盒子输入是什么!输出是什么!输入输出清晰,功能清晰,非常“干净”!如图:

JS组合函数实例分析

与此同时,它还能被搬来搬去,或再继续组装。

我们回到 uniqueWords() 函数的内部,它的数据流也是清晰的:

uniqueWords <-- unique <-- words <-- text

封装盒子

上面的封装 uniqueWords 盒子很 nice ,如果要不断的封装像 uniqueWords 的盒子,我们要一个一个的去写吗?

function uniqueWords(str) {    return unique( words( str ) );}function uniqueWords_A(str) {    return unique_A( words_A( str ) );}function uniqueWords_B(str) {    return unique_B( words_B( str ) );}...

所以,一切为了偷懒,我们可以写一个功能更加强大的函数来实现自动封装盒子:

function compose2(fn2,fn1) {    return function composed(origValue){        return fn2( fn1( origValue ) );    };}// es6 箭头函数形式写法var compose2 =    (fn2,fn1) =>        origValue =>            fn2( fn1( origValue ) );

JS组合函数实例分析

接着,调用就变成了这样:

var uniqueWords = compose2( unique, words );var uniqueWords_A = compose2( unique_A, words_A );var uniqueWords_B = compose2( unique_B, words_B );

太清晰了!

任意组合

上面,我们组合了两个函数,实际上我们也可以组合 N 个函数;

finalValue <-- func1 <-- func2 <-- ... <-- funcN <-- origValue

JS组合函数实例分析

比如用一个 compose 函数来实现(敲重点):

function compose(...fns) {    return function composed(result){        // 拷贝一份保存函数的数组        var list = fns.slice();        while (list.length > 0) {            // 将最后一个函数从列表尾部拿出            // 并执行它            result = list.pop()( result );        }        return result;    };}// ES6 箭头函数形式写法var compose =    (...fns) =>        result => {            var list = fns.slice();            while (list.length > 0) {                // 将最后一个函数从列表尾部拿出                // 并执行它                result = list.pop()( result );            }            return result;        };

基于前面 uniqueWords(..) 的例子,我们进一步再增加一个函数来处理(过滤掉长度小于等于4的字符串):

function skipShortWords(list) {    var filteredList = [];    for (let i = 0; i < list.length; i++) {        if (list[i].length > 4) {            filteredList.push( list[i] );        }    }    return filteredList;}var text = "To compose two functions together";var biggerWords = compose( skipShortWords, unique, words );var wordsUsed = biggerWords( text );wordsUsed;// ["compose", "functions", "together"]

这样 compose 函数就有三个入参且都是函数了。我们还可以利用偏函数的特性实现更多:

function skipLongWords(list) {  }var filterWords = partialRight( compose, unique, words ); // 固定 unique 函数 和 words 函数var biggerWords = filterWords( skipShortWords );var shorterWords = filterWords( skipLongWords );biggerWords( text );shorterWords( text );

filterWords 函数是一个更具有特定功能的变体(根据第一个函数的功能来过滤字符串)。

compose 变体

compose(..)函数非常重要,但我们可能不会在生产中使用自己写的 compose(..),而更倾向于使用某个库所提供的方案。了解其底层工作的原理,对我们强化理解函数式编程也非常有用。

我们理解下 compose(..) 的另一种变体 —— 递归的方式实现:

function compose(...fns) {    // 拿出最后两个参数    var [ fn1, fn2, ...rest ] = fns.reverse();    var composedFn = function composed(...args){        return fn2( fn1( ...args ) );    };    if (rest.length == 0) return composedFn;    return compose( ...rest.reverse(), composedFn );}// ES6 箭头函数形式写法var compose =    (...fns) => {        // 拿出最后两个参数        var [ fn1, fn2, ...rest ] = fns.reverse();        var composedFn =            (...args) =>                fn2( fn1( ...args ) );        if (rest.length == 0) return composedFn;        return compose( ...rest.reverse(), composedFn );    };

通过递归进行重复的动作比在循环中跟踪运行结果更易懂,这可能需要更多时间去体会;

基于之前的例子,如果我们想让参数反转:

var biggerWords = compose( skipShortWords, unique, words );// 变成var biggerWords = pipe( words, unique, skipShortWords );

只需要更改 compose(..) 内部实现这一句就行:

...        while (list.length > 0) {            // 从列表中取第一个函数并执行            result = list.shift()( result );        }...

虽然只是颠倒参数顺序,这二者没有本质上的区别。

抽象能力

你是否会疑问:什么情况下可以封装成上述的“盒子”呢?

这就很考验 —— 抽象的能力了!

实际上,有两个或多个任务存在公共部分,我们就可以进行封装了。

比如:

function saveComment(txt) {    if (txt != "") {        comments[comments.length] = txt;    }}function trackEvent(evt) {    if (evt.name !== undefined) {        events[evt.name] = evt;    }}

就可以抽象封装为:

function storeData(store,location,value) {    store[location] = value;}function saveComment(txt) {    if (txt != "") {        storeData( comments, comments.length, txt );    }}function trackEvent(evt) {    if (evt.name !== undefined) {        storeData( events, evt.name, evt );    }}

在做这类抽象时,有一个原则是,通常被称作 DRY(don't repeat yourself),即便我们要花时间做这些非必要的工作。

抽象能让你的代码走得更远! 比如上例,还能进一步升级:

function conditionallyStoreData(store,location,value,checkFn) {    if (checkFn( value, store, location )) {        store[location] = value;    }}function notEmpty(val) { return val != ""; }function isUndefined(val) { return val === undefined; }function isPropUndefined(val,obj,prop) {    return isUndefined( obj[prop] );}function saveComment(txt) {    conditionallyStoreData( comments, comments.length, txt, notEmpty );}function trackEvent(evt) {    conditionallyStoreData( events, evt.name, evt, isPropUndefined );}

这样 if 语句也被抽象封装了。

抽象是一个过程,程序员将一个名字与潜在的复杂程序片段关联起来,这样该名字就能够被认为代表函数的目的,而不是代表函数如何实现的。通过隐藏无关的细节,抽象降低了概念复杂度,让程序员在任意时间都可以集中注意力在程序内容中的可维护子集上。—— 《程序设计语言》

我们在本系列初始提到:“一切为了创造更可读、更易理解的代码。”

从另一个角度,抽象就是将命令式代码变成声命式代码的过程。从“怎么做”转化成“是什么”。

命令式代码主要关心的是描述怎么做来准确完成一项任务。声明式代码则是描述输出应该是什么,并将具体实现交给其它部分。

比如 ES6 增加的结构语法:

function getData() {    return [1,2,3,4,5];}// 命令式var tmp = getData();var a = tmp[0];var b = tmp[3];// 声明式var [ a ,,, b ] = getData();

“JS组合函数实例分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: JS组合函数实例分析

本文链接: https://www.lsjlt.com/news/340926.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JS组合函数实例分析
    本篇内容介绍了“JS组合函数实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!组合函数含义函数编程就像拼乐高!乐高有各式各样的零部件,我...
    99+
    2023-07-02
  • JS函数实例分析
    这篇“JS函数实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JS函数实例分析”文章...
    99+
    2022-10-19
  • js中async函数结合promise的示例分析
    这篇文章主要为大家展示了“js中async函数结合promise的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js中async函数结合promise的...
    99+
    2022-10-19
  • js函数的示例分析
    这篇文章主要介绍了js函数的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。函数1 函数默认值func = (l,...
    99+
    2022-10-19
  • js中数组的示例分析
    小编给大家分享一下js中数组的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!创建一个数组:// 字面量方式: ...
    99+
    2022-10-19
  • vue封装组件js实例分析
    本文小编为大家详细介绍“vue封装组件js实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue封装组件js实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。什么是组件化:组件化就是将一个页面拆分成一...
    99+
    2023-06-30
  • LINQ函数集合的示例分析
    这篇文章主要为大家展示了“LINQ函数集合的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“LINQ函数集合的示例分析”这篇文章吧。LINQ函数集合我已经在C#3.0的介绍LINQ专题中提...
    99+
    2023-06-17
  • JS函数防抖和函数节流的示例分析
    这篇文章主要介绍JS函数防抖和函数节流的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!概述函数防抖和函数节流都是定义一个函数,该函数接收一个函数作为参数,并返回一个添加了防抖或节流功能后的函数。因此可以将函数...
    99+
    2023-06-15
  • js中函数式编程的示例分析
    这篇文章主要为大家展示了“js中函数式编程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js中函数式编程的示例分析”这篇文章吧。(1)平常写的函数大多...
    99+
    2022-10-19
  • JS前端面试数组扁平化手写flat函数示例分析
    本文小编为大家详细介绍“JS前端面试数组扁平化手写flat函数示例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“JS前端面试数组扁平化手写flat函数示例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。题...
    99+
    2023-07-02
  • js中数组实现权重概率分配的示例分析
    小编给大家分享一下js中数组实现权重概率分配的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!代码如下: function weight_rand(arr){  ...
    99+
    2022-10-19
  • js遍历集合的示例分析
    这篇文章将为大家详细讲解有关js遍历集合的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Array可以使用下标,Map和Set不能使用下标,ES6引入了itera...
    99+
    2022-10-19
  • JavaScript数组、字符串和数学函数实例分析
    这篇文章主要介绍了JavaScript数组、字符串和数学函数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript数组、字符串和数学函数实例分析文章都会有所...
    99+
    2022-10-19
  • C++实例分析组合数的计算与排列组合的产生
    目录组合数的计算使用加法递推—O(n^2)使用乘法递推—O(n)排列和组合的产生(无重集元素)全排列一般组合全组合由上一排列产生下一排列由上一组合产生下一组合...
    99+
    2022-11-13
  • C++函数参数实例分析
    这篇文章主要介绍了C++函数参数实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++函数参数实例分析文章都会有所收获,下面我们一起来看看吧。一、函数参数的默认值C++ 中可以在函数声明时为参数提供一个默...
    99+
    2023-06-30
  • Python函数参数实例分析
    本文小编为大家详细介绍“Python函数参数实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python函数参数实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.函数参数# 1.位置参数...
    99+
    2023-06-28
  • Vue函数式组件的示例分析
    这篇文章将为大家详细讲解有关Vue函数式组件的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。函数式组件特点:没有管理任何状态没有监听任何传递给它的状态没有生命周期...
    99+
    2022-10-19
  • JS组件封装的示例分析
    这篇文章主要介绍了JS组件封装的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、扩展已经存在的组件1、需求背景很多时候,我们使用j...
    99+
    2022-10-19
  • js数组运用之元素能否通过指定函数的示例分析
    这篇文章将为大家详细讲解有关js数组运用之元素能否通过指定函数的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。这次我们来出一个小题目,我们一起来算一下可好?请看题...
    99+
    2022-10-19
  • java数组的实例分析
    这篇文章主要介绍“java数组的实例分析”,在日常操作中,相信很多人在java数组的实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java数组的实例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作