Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS 函数式编程 #62

Open
coconilu opened this issue Aug 27, 2018 · 0 comments
Open

JS 函数式编程 #62

coconilu opened this issue Aug 27, 2018 · 0 comments

Comments

@coconilu
Copy link
Owner

coconilu commented Aug 27, 2018

概述

函数式编程,最重要的特征就是函数可以作为参数被传入另一个函数,也可以作为返回值被另一个函数返回。刚好JavaScript支持这样的操作,在JS里函数是一个对象,被当做一等公民对待。

有两个JS开源库就是用函数式思想完成的:

  1. Underscore
  2. Lodash

函数式编程的语法前提

  1. Function 对象
Function.length,指该函数有多少个必须要传入的参数,数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数。
Function.name,返回函数实例的名称。只读。
Function.prototype,原型。
Function.prototype.apply(),函数调用自身, 可以指定的绑定到this的对象,以及传入该函数的参数(数组或类数组形式)。
Function.prototype.bind(),返回一个新函数,和原函数具有相同的函数体,并且新函数的this绑定到bind()的第一个参数,也可以传入预设的参数。
Function.prototype.call(),函数调用自身, 可以指定的绑定到this的对象,以及传入该函数的参数(列表形式)。
Function.prototype.toString(),返回函数源代码的一个字符串
  1. arguments 对象
arguments.callee,返回当前执行的函数,也就是arguments拥有者。不推荐使用,给函数附上名字可以替代。
arguments.length,返回传递给当前函数的参数数量。

当非严格模式中的函数有包含剩余参数、默认参数和解构赋值,那么arguments对象中的值不会跟踪参数的值(反之亦然)。

函数式编程和命令式编程

函数式编程关心数据的映射,命令式编程关心解决问题的步骤。

因为函数式编程追求的是:

  1. 无副作用,不会修改外部系统的状态
  2. 幂等性,就是相同输入,保证相同输出

执行速度

一般而言,函数越多,就越会越影响运行速度,因为JS引擎的执行栈压入或弹出一个函数执行上下文都是会消耗性能。

但是,自从V8引擎推出后,这不再是大问题。因为V8引擎会分析代码并优化代码,一些函数会被内联的方式“粘”到另一个函数里面。更甚的是,会把函数优化成静态代码。

所以,不用再担心函数数量过多会影响整个系统的性能。

通用概念

  1. 作用域
全局作用域,最长声明周期的变量
函数作用域,每个函数都是一个调用上下文,独立于其它函数
词法作用域,箭头函数就是词法作用域,它没有自己的this、arguments对象
动态作用域,特指this、arguments,它们在不同的函数作用域指向不同的对象
  1. 闭包
闭包就是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。
遮蔽,自由变量会被内函数的局部变量遮蔽,遮蔽的自由变量会访问不到

函数式编程的特点

  1. 函数是“第一等公民”——函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
  2. 只用“表达式”,不用“语句”——为了处理运算(computation),不考虑系统的读写(I/O)。
  3. 没有“副作用”——函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。
  4. 不修改状态——使用参数保存状态,最好的例子就是递归。
  5. 引用透明——函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。

函数的纯度

  1. 结果仅依赖输入且与系统外部状态无关
由此衍生的应用:
1. 函数记忆
2. 延迟求值:currying、偏函数、函子

函子指函数可以被一层一层包裹,但是书写的时候可以像链式调用一样,参考:

function Effect(f) {
  return {
    map(g) {
      return Effect(x => g(f(x)));
    },
    runEffects(x) {
      return f(x);
    }
  };
}

函子会返回一系列包裹在一起的函数,它一般有一个触发所有函数的扳机

  1. 没有副作用,意味着不会修改系统外部状态

基于流的编程

  1. 链式调用,需要规范每一次操作的返回值
  2. 管道,一般作用在集合上
  3. promise,异步调用

参考

书籍

《JavaScript 函数式编程》

链接

HOW TO DEAL WITH DIRTY SIDE EFFECTS IN YOUR PURE FUNCTIONAL JAVASCRIPT
如何使用纯函数式 JavaScript 处理脏副作用
可能是最好的函数式编程入门
函数式编程初探

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant