JavaScript 高级程序设计(特别是对浏览器差异的复杂处理),通常很困难也很耗时。
为了应对这些调整,许多的 JavaScript (helper) 库应运而生,这些 JavaScript 库常被称为 JavaScript 框架。介绍一些日常用的 JavaScript 框架:
jQuery
Prototype
MooTools
所有这些框架都提供针对常见 JavaScript 任务的函数,包括动画、DOM 操作以及 Ajax 处理。
jQuery
jQuery 是目前最受欢迎的 JavaScript 框架。
它使用 CSS 选择器来访问和操作网页上的 HTML 元素(DOM 对象)。
jQuery 同时提供 companion UI(用户界面)和插件。
许多大公司在网站上使用 jQuery:
Microsoft
IBM
Netflix
Prototype
Prototype 是一种库,提供用于执行常见 web 任务的简单 API。
API 是应用程序编程接口(Application Programming Interface)的缩写。它是包含属性和方法的库,用于操作 HTML DOM。
Prototype 通过提供类和继承,实现了对 JavaScript 的增强。
MooTools
MooTools 也是一个框架,提供了可使常见的 JavaScript 编程更为简单的 API。
MooTools 也含有一些轻量级的效果和动画函数。
其他框架
下面是其他一些在上面未涉及的框架:
YUI - Yahoo! User Interface Framework,涵盖大量函数的大型库,从简单的 JavaScript 功能到完整的 internet widget。
Ext JS - 可定制的 widget,用于构建富因特网应用程序(rich Internet applications)。
Dojo - 用于 DOM 操作、事件、widget 等的工具包。
script.aculo.us - 开源的 JavaScript 框架,针对可视效果和界面行为。
UIZE - Widget、AJAX、DOM、模板等等。
我们前篇谈了很多关于【闭包】的理解了,所以你应该会知道,我们现在将要谈的就是 ——【异步】。
我们为什么觉得“异步问题”复杂呢?
其中很重要的一个原因是 —— 时间!时间将我们对数据的操作、管理,变复杂了好几个量级!
(需要特别提出并明确的是: 异步和同步之间是可以相互转化的! 我们使用异步或者同步取决于 —— 如何使代码更加可读!)
函数式编程给出了实现“代码更可读”的落地原则(已多次回顾):
所以我们可以期待,异步在函数式编程中的表现!
上代码:
onCustomer(..) 和 onOrders(..) 是两个【回调函数】释义,两者执行的先后顺序并不能确定,所以它是一个基于时间的复杂状态。
释义:回调函数其实就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。
通常来说,我们最先想到的是:把 lookupOrders(..) 写到 onCustomer(..) 里面,那我们就可以确认 onOrders(..) 会在 onCustomer(..) 之后运行。
这样写,对吗?
不对!因为 onCustomer(..) 、 onOrders(..) 这两个回调函数的关系更像是一种竞争关系(都是赋值 customer.orders ), 它们应该并行执行 , 而不是串行执行 。
即:我不管你们谁先执行,谁先执行完,谁就赋值给 customer.orders !
那我们的思路应该是:
不过,这样让代码又变得更加难阅读!!函数内部赋值依赖于外部变量、甚至受外部回调函数的影响。
那究竟怎么办呢?
最终,我们借用 JS promise 减少这个时间状态,将异步转成同步:
两个 .then(..) 运行之前, lookupCustomer(..) 和 lookupOrders(..) 已被同步调用,满足并行执行,谁先结束,谁赋值给 customer.orders ,所以我们不需要知道谁先谁后!
在这样的实现下,不再需要时间先后的概念!减少了时间状态!!代码的可读性更高了!!
这是一个 积极的数组 ,因为它们同步(即时)地操作着离散的即时值或值的列表/结构上的值。
什么意思?
a 映射到 b,再去修改 a ,b 不会收到影响。
而这,是一个 惰性的数组 , mapLazy(..) 本质上 “监听” 了数组 a,只要一个新的值添加到数组的末端(push(..)),它都会运行映射函数 v =>v * 2 并把改变后的值添加到数组 b 里。
什么意思?
a 映射到 b,再去修改 a ,b 也会修改。
原来,后者存在 异步 的概念。
让我们来想象这样一个数组,它不只是简单地获得值,它还是一个懒惰地接受和响应(也就是“反应”)值的数组,比如:
设置“懒惰的数组” a 的过程是异步的!
b ,是 map 映射后的数组,但更重要的是,b 是 反应性 的,我们对 b 加了一个类似监听器的东西。
这里直接给出解答:
这里再多小结一句:时间让异步更加复杂,函数式编程在异步下的运用就是减少或直接干掉时间状态。
想象下 a 还可以被绑定上一些其他的事件上,比如说用户的鼠标点击事件和键盘按键事件,服务端来的 websocket 消息等。
上述的 LazyArray 又可叫做 observable !(当然,它不止用在 map 方法中)
现在已经有各种各样的 Observables 的库类,最出名的是 RxJS 和 Most 。
以 RxJS 为例:
不仅如此,RxJS 还定义了超过 100 个可以在有新值添加时才触发的方法。就像数组一样。每个 Observable 的方法都会返回一个新的 Observable,意味着他们是链式的。如果一个方法被调用,则它的返回值应该由输入的 Observable 去返回,然后触发到输出的 Observable里,否则抛弃。
比如:
本篇介绍了【异步】在函数式编程中的表现。
原则是:对于那些异步中有时态的操作,基础的函数式编程原理就是将它们变为无时态的应用。即 减少时间状态 !
就像 promise 创建了一个单一的未来值,我们可以创建一个积极的列表的值来代替像惰性的observable(事件)流的值。
我们介绍了 RxJS 库,后续我们还会介绍更多优美的 JS 函数式编程库!
(俗话说的好,三方库选的好,下班都很早!!)
现在本瓜有点明白那句话了:看一门语言是不是函数式编程,取决于它的核心库是不是函数式编程。
也许我们还不熟悉像 RxJS 这类库,但我们慢慢就会越来越重视它们,越来越使用它们,越来越领会到它们!!
异步,以上。