探索JavaScript函数式编程的来龙去脉-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

探索JavaScript函数式编程的来龙去脉

简介: 阿里巴巴前端工程师逸翾对JavaScript中的函数进行了详细讲解。首先谈及了环境作用域,其中说明了块级作用域和作用域链,接着解释了闭包的作用,最后重点分析了JavaScript的函数式编程,包括纯函数、函数柯里化和高阶函数。
阿里巴巴前端工程师逸翾对JavaScript中的函数进行了详细讲解。首先谈及了环境作用域,其中说明了块级作用域和作用域链,接着解释了闭包的作用,最后重点分析了JavaScript的函数式编程,包括纯函数、函数柯里化和高阶函数。

数十款阿里云产品限时折扣中,赶快点击这里,领券开始云上实践吧!

直播视频精彩回顾

以下是精彩视频内容整理:

环境作用域

JavaScript环境作用域与其它编程语言不太一样,需要做一些特殊处理。首先,执行环境是JavaScript中最重要的一个概念,执行环境定义了变量或者函数有权访问的其他数据。全局环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象;其次,每个函数都有自己的执行环境,并且,当代码在一个环境中执行时,会创建变量对象的一个作用域链。

4057baad9ef9f45d12fb3d00d9a8bae4f70d625a

作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。作用域中变量的值是在执行过程中产生的确定值,而作用域却是在函数创建时就确定了。

块级作用域

304096630bcadabffc4facc148937ffbbf8787f6

以前较长使用的是作用域var,使用var声明的变量会自动添加最接近的环境中。不论var声明的变量处于当前作用域的第几行,都会提升到作用域的头部,并被初始化为undefined。这种行为叫作变量提升,如图所示,执行for循环,for循环没有运行在一个function中,此时声明的变量会添加到最接近的环境中,即全局环境,在浏览器中会添加到windows上面,虽然在开始没有声明i,但是在执行for以后,i就被声明出来,再打印i就被赋值了。正常情况下,for中声明的变量在for外面打印,应该是超出作用域范围了,但i还是能被打印出来,说明var被添加到全局环境中。

为了解决var存在的问题,块级作用域中出现了let/const命令,它们的作用类似var。var的作用域是函数作用域,let作用域是在大括号中。let不允许在相同作用域内,重复声明同一个变量,只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响,不存在变量提升。

Const命令声明只读变量,一旦声明后,变量值就不能改变,必须立即初始化,否则就会报错。Const本质是变量指向地址不可改变,它可以保证指向地址的指针是固定的,指向的数据结构不可控制。

作用域链

c200e45eea495847481b288dd9b32d716f3cc4cd

在作用域中使用的变量,却没有在当前作用域中声明,就需要到另一个作用域中取。如图所示,fn是在全局作用域中创建的,在show中被调用,在创建函数外面不能取到里面的值,要到『创建』这个函数的那个作用域中取值,而不是『调用』这个函数的作用域中取值。如果在上一个作用域中也没找到变量就要继续向上跨,直到跨到全局作用域为止,这个过程即为作用域链。

 

闭包

2c9952fe99cab1b6ded8328cf6cff6a27ed5c4d9

函数内部可以直接读取全局变量,函数外部自然无法读取函数内的局部变量。但有时候我们需要保留函数内部的值,如何从外部读取局部变量呢?在函数内部再定义一个函数,进而取出想要的值。如图所示,在f1内部定义了一个f2,可以在外围取到函数内部值,实现闭包的作用。

闭包就是将函数内部和函数外部连接起来的一座桥梁,闭包使得函数能够读取其他函数内部变量的函数。闭包也存在隐患,由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包。闭包会在父函数外部,改变父函数内部变量的值。

 

函数式编程

函数式编程(functional programming)或称函数程序设计,又称泛函编程,是一种编程典范,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数式编程强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。

函数式编程领域中函数是第一等公民,有以下四个优点:

1.         使语义更加清晰

2.         强调结果而非过程,可复用性更高

3.         代码更少,可维护性更好

4.         作用域局限,副作用少

函数式编程中一些比较重要的编程实践包括纯函数、函数柯里化和高阶函数等。

纯函数

2b0c7ad2df89480a1664c11f0b4d567318512557

对于相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用,也不依赖外部环境的状态。如图所示,不纯函数中,定义min变量,再定义一个checkage函数检查大于18年龄的变量,虽然checkage只接收一个变量,由于min是可变的,可能违背相同的输入会得到相同的输出这一原则;而纯函数的18是定值,输出永远是相同的,应用箭头函数,极大精简了代码书写。

函数柯里化

22c9d0e7839a260d866b74d5096567fd0f77ad36

柯里化给函数分步传递参数,每次传递参数后,部分应用参数,并返回一个更具体的函数接受剩下的参数,中间可嵌套多层这样的接受部分参数函数,逐步缩小函数的适用范围,逐步求解,直至返回最后结果。

如图所示,第一幅图不够柯里化,定义add函数,一次性传输并一次性得出结果;第二幅图为柯里化函数,在add中又返回了一个方法,可以逐步求解;第三幅图利用箭头函数特性,简化方法,定义add时先传x再传y,返回x+y,执行结果与之前完全相同。柯里化本质是使用闭包返回一个函数。

高阶函数

087b61c20c776221827da4668180899780c3593e

高阶函数指函数可以作为参数被传递或者作为返回值输出,例如map、reduce和filter。如图所示,使用这些高级函数,可以大量减少代码书写量,在箭头函数的加持下,代码变得更加简洁。日常工作中,高阶函数被应用在很多地方,比如在react中创造一个具有特殊操作的class,提高组件可复用性。

 

本文由云栖志愿小组毛鹤整理,编辑百见

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章