JS函数式编程实现XDM一


Posted in Javascript onJune 16, 2022

盲猜一个:如果你有看过

《medium 五万赞好文-《我永远不懂 JS 闭包》》

你一定会对 JS 的【函数】有更多兴趣!

皮一下,很舒服~ 没错!JS 就是轻量级的函数式编程!

拆解一下这句话,品味一下~

本瓜将借助《JavaScript 轻量级函数式编程》一书带领你先透析它的落脚点函数式编程,然后再看看 JS 为什么被称为是 “轻量的”!

此篇是《JS如何函数式编程》系列的第一篇,点赞?关注?持续追踪!

FP 概览

重要性

函数式编程(FP),不是一个新的概念,它几乎贯穿了整个编程史。直到最近几年,函数式编程才成为整个开发界的主流观念。

函数式编程有完善且清晰的原则,一旦我们知道这些原则,我们将能更加快速地读懂代码,定位问题。这是为什么函数式编程重要的原因!

比如:你可能写过一些命令式的代码,像 if 语句和 for 循环这样的语句。这些语句旨在精确地指导计算机如何完成一件事情。而声明式代码,以及我们努力遵循函数式编程原则所写出的代码,更专注于描述最终的结果。

函数式编程以另一种方式来思考代码应该如何组织才能使数据流更加明显,并能让读者很快理解你的思想。

记住,你编写的每一行代码之后都要有人来维护,这个人可能是你的团队成员,也可能是未来的你。

最初的函数

函数式编程不是仅仅用 function 这个关键词来编程,就像面向对象编程不仅仅是用了对象就算是。

函数的真正意义是什么?

回到最初的起点,我们心中的函数一定是这样的:

JS函数式编程实现XDM一

f(x) = 2x2 + 3,这是数学上真正的函数。那这和函数式编程有什么关系呢?

函数的本质是【映射】。以一个优雅的方式来描述一组值和另一组值的映射关系,即函数的输入值与输出值之间的关联关系。

在编程中,它或许有许多个输入值,或许没有。它或许有一个输出值( return 值),或许没有。

如果你计划使用函数式编程,你应该尽可能多地使用函数,而不是程序。你所有编写的 function 应该接收输入值,并且返回输出值。(这么做的原因是多方面的,后续会一一介绍)

这里,输入值就是函数传参,输出值就是return的东西。(如果你没有 return 值,或者你使用 return;,那么则会隐式地返回 undefined 值。)

思考“return”

  • 思考以下代码:
function foo(x) {
    if (x > 10) return x + 1;
    var y = x / 2;
    if (y > 3) {
        if (x % 2 == 0) return x;
    }
    if (y > 1) return y;
    return x;
}

foo(2) 返回什么? foo(4) 返回什么? foo(8), foo(12) 呢?

  • 将上述代码变形,请思考:
function foo(x) {
    var retValue;
    if (retValue == undefined && x > 10) {
        retValue = x + 1;
    }
    var y = x / 2;
    if (y > 3) {
        if (retValue == undefined && x % 2 == 0) {
            retValue = x;
        }
    }
    if (retValue == undefined && y > 1) {
        retValue = y;
    }
    if (retValue == undefined) {
        retValue = x;
    }
    return retValue;
}

这样写会更容易理解吗?

在每个 retValue 可以被设置的分支, 这里都有个守护者以确保 retValue 没有被设置过才执行。(?)

相比在函数中提早使用 return,我们更应该用常用的流控制( if 逻辑 )来控制 retValue 的赋值。到最后,我们 return retValue。

用 return 来实现流控制,会创造更多的隐含意义。

再来思考以下代码:

// 通过一个函数修改变量 y 的值
var y;
function foo(x) {
    y = (2 * Math.pow( x, 2 )) + 3;
}
foo( 2 );
y;

但是我们也可以这样写:

function foo(x) {
    return (2 * Math.pow( x, 2 )) + 3;
}
var y = foo( 2 );
y;

后一个版本更有优势吗?

答案是肯定的:有!

后一个版本中的 return 表示一个显式输出,而前者的 y 赋值是一个隐式输出。

通常,开发人员喜欢显式模式而不是隐式模式。

为什么说后者 return 出来的就是显式的?而前者的 y 赋值是隐式的?

这个例子可以给你答案:

function sum(list) {
    var total = 0;
    for (let i = 0; i < list.length; i++) {
        if (!list[i]) list[i] = 0; // list 使用了 nums 的引用,不是对 [1,3,9,..] 的值复制,而是引用复制。
        total = total + list[i];
    }
    return total;
}
var nums = [ 1, 3, 9, 27, , 84 ];
sum( nums );            // 124

这段代码,除了 return 的输出,还有没有其它输出可能改变到函数外部参数 nums 的值?

是有的!就是在注释的一行,我们无意中改变了 nums 。

console.log(nums) // [1, 3, 9, 27, 0, 84]

JS 对数组、对象和函数都使用引用和引用复制,我们可以很容易地从函数中创建输出,即使是无心的。

这个隐式函数输出在函数式编程中有一个特殊的名称:副作用。

没有副作用的函数也有一个特殊的名称:纯函数,这个概念十分重要,后面对有更多讨论!

高阶函数

一个函数如果可以接受或返回一个甚至多个函数,它被叫做高阶函数。

其中最强大的就是:【闭包】。

我们将在的后续举例中大量使用闭包。它可能是所有函数式编程中最重要的基础。

此处举一小例:

假设你需要将两个值相加,一个你已经知道,另一个还需要后面才能知道,你可以使用闭包来记录第一个输入值:

function makeAdder(x) {
    return function sum(y){
        return x + y;
    };
}
//我们已经分别知道作为第一个输入的 10 和 37
var addTo10 = makeAdder( 10 );
var addTo37 = makeAdder( 37 );
// 紧接着,我们指定第二个参数
addTo10( 3 );            // 13
addTo10( 90 );            // 100
addTo37( 13 );            // 50

这种在连续函数调用中指定输入,是函数式编程中非常普遍的形式。

它可分为两类:偏函数应用和柯里化。后续会展开。

具名函数

我们提倡要用具名函数,而不是匿名函数,这更有利于我们语义化代码,比如getPreferredName(..),操作意图很明确,并且可以很好的回溯问题,防止出现 (anonymous function) 。

但是 => 箭头函数除外,箭头函数还是得有效利用。

=> 箭头函数令人兴奋的地方在于它几乎完全遵循函数的数学符号,特别是像 Haskell 这样的函数式编程语言。它能简化、优化代码片段中的空间。

丢掉“this"

JavaScript 中的 this 绑定规则是真的难记,好消息是我们将把 this 丢弃掉,不去理会它。

这样做的内核原因是:this 是函数的一个隐式的输入参数。前面我们提到通常,开发人员喜欢显式模式而不是隐式模式。,这样的隐式输入违背了我们的原则。

阶段小结

函数是强大的!

  • 我们学习函数式编程的全部理由是为了书写更具可读性的代码。
  • 程序中,函数不仅仅是一个语句或者操作的集合,而是需要一个或多个输入(理想情况下只需一个!)和一个输出。开发人员喜欢显式输入输出而不是隐式输入输出。
  • 函数内部的函数可以取到闭包外部变量,并记住它们以备日后使用。这是所有程序设计中最重要的概念之一,也是函数式编程的基础。
  • 要警惕匿名函数,特别是 => 箭头函数。虽然在编程时用起来很方便,但是会对增加代码阅读的负担。
  • 别用 this 敏感的函数。这不需要理由。

以上就是JS函数式编程实现XDM一的详细内容,更多关于JS函数式编程XDM的资料请关注三水点靠木其它相关文章!


Tags in this post...

Javascript 相关文章推荐
jquery ajax跨域解决方法(json方式)
Feb 04 Javascript
javasciprt下jquery函数$.post执行无响应的解决方法
Mar 13 Javascript
JS实现OCX控件的事件响应示例
Sep 17 Javascript
jQuery学习笔记之jQuery+CSS3的浏览器兼容性
Jan 19 Javascript
js跨域请求的5中解决方式
Jul 02 Javascript
JavaScript中的Repaint和Reflow用法详解
Jul 27 Javascript
浅谈js中function的参数默认值
Feb 20 Javascript
前端把html表格生成为excel表格的实例
Sep 19 Javascript
浅谈angular4.0中路由传递参数、获取参数最nice的写法
Mar 12 Javascript
详解在React里使用"Vuex"
Apr 02 Javascript
JavaScript常用事件介绍
Jan 21 Javascript
原生js代码能实现call和bind吗
Jul 31 Javascript
正则表达式基础与常用验证表达式
Jun 16 #Javascript
使用compose函数优化代码提高可读性及扩展性
html中两种获取标签内的值的方法
Jun 16 #jQuery
JavaScript前端面试扁平数据转tree与tree数据扁平化
Jun 14 #Javascript
vue如何在data中引入图片的正确路径
Jun 05 #Vue.js
Vue Mint UI mt-swipe的使用方式
Jun 05 #Vue.js
vue @ ~ 相对路径 路径别名设置方式
Jun 05 #Vue.js
You might like
php获取textarea的值并处理回车换行的方法
2014/10/20 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
laravel框架select2多选插件初始化默认选中项操作示例
2020/02/18 PHP
php操作redis命令及代码实例大全
2020/11/19 PHP
javascript中的变量作用域以及变量提升详细介绍
2013/10/24 Javascript
如何获取网站icon有哪些可行的方法
2014/06/05 Javascript
JavaScript监听文本框回车事件并过滤文本框空格的方法
2015/04/16 Javascript
Wireshark基本介绍和学习TCP三次握手
2016/08/15 Javascript
jQuery双向列表选择器select版
2016/11/01 Javascript
使用contextMenu插件实现Bootstrap table弹出右键菜单
2017/02/20 Javascript
mongoose中利用populate处理嵌套的方法
2017/05/26 Javascript
详解Vue2.0 事件派发与接收
2017/09/05 Javascript
详解vue2 $watch要注意的问题
2017/09/08 Javascript
Angularjs之如何在跨域请求中传输Cookie的方法
2018/06/01 Javascript
详解vuex中action何时完成以及如何正确调用dispatch的思考
2019/01/21 Javascript
Node 代理访问的实现
2019/09/19 Javascript
layui form表单提交后实现自动刷新
2019/10/25 Javascript
js简单粗暴的发布订阅示例代码
2021/01/23 Javascript
[01:00:49]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第二场 1月31日
2021/03/11 DOTA
python使用urllib2模块获取gravatar头像实例
2013/12/18 Python
python操作mysql中文显示乱码的解决方法
2014/10/11 Python
Python中文件操作简明介绍
2015/04/13 Python
解决Python2.7读写文件中的中文乱码问题
2018/04/12 Python
caffe binaryproto 与 npy相互转换的实例讲解
2018/07/09 Python
解决Pycharm下面出现No R interpreter defined的问题
2018/10/29 Python
python小技巧——将变量保存在本地及读取
2020/11/13 Python
Python爬虫进阶之爬取某视频并下载的实现
2020/12/08 Python
50个强大璀璨的CSS3/JS技术运用实例
2010/02/27 HTML / CSS
台湾网购生鲜第一品牌:i3Fresh爱上新鲜
2017/10/26 全球购物
鉴定评语大全
2014/05/05 职场文书
本科生求职信
2014/06/17 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书
工伤死亡理赔协议书
2014/10/20 职场文书
幼儿园2016年感恩节活动总结
2016/04/01 职场文书
蓝天保卫战收官在即 :15行业将开展环保分级评价
2019/07/19 职场文书
MySQL创建管理KEY分区
2022/04/13 MySQL