下划线的学习1
下划线是个JS底层小类库,主要是为弥补JS基础部分的不足.提供了一些集合,对象,函数,及其它的一些支持.实际上应该把它当成JS的一部分来看.考虑到它短小精悍,应该直接看代码及相关英文文档.
学习它一是为了加强一下JS,学以致用,二是加强一下函数式编程的实战,考虑到它实在是太短小,虽然英文比较烂但还是直接看原文文档,并根据学习理解意译下来.
下线线是什么?是_, 也就是underscore.js这个库,JS的变是名可以有两个特殊符号就是$和_,可见这两个符号,的确是被重要的库给占领了.这就是占领制高点,另一个$不用说都知道是什么了.当然还有个BB(Backbone),因为没有占领制高点,类似的库就比较多了.
下划线怎么看怎么象下划钱,读同来就是瞎花钱,$也是钱钱,难道说这就是巧合?可见_和$就是赚钱的工具.以下就下划线就都用_代替.
_是个很小的JS库,主要提供象Prototype.js, Ruby等类似功能,但不需要扩展JS语言本身.而且它主要用于$及BB(Backbone)的支持._大约有80多个函数,以支持常用的Map, Select, Invoke及其它一些常用功能,而这些大多数的以后浏览器可以原生支持,那么它可以提供一个浏览器的包装,可见现在就使用_,在未来也不会有问题._还经过完整全面的测试,可以放心使用.顺便补充下,网站是http://underscorejs.org
Collection Functions (Arrays or Objects)
迭代: each 迭代器,别名forEach
语法 _each(list, iterator, [context]) 如果list是数组,则iterator参数是(element, index, list), 如果list是对象,则iterator参数是(value, key, list)
示例: _.each({ one: 1, two: 2, three: 3 }, function (value, key) { alert(key + value); });
本人注意到一个共性,就是_的很多调用方式都是这样子(list, iterator, [context]),别小看这三个参数,这里面包含了很深刻的思想.根据可见资料看出,大多数人无法很好的理解这些库就是因为不理解函数式编程,以及面向对象的一些底层原理.只会用一些皮毛,而无法使用其精髓.
看到这里,就发现学习_学对了,果然是精妙.
首先,大多数操作就是高阶函数,就是函数式编程的一个最广泛应用.each(list, iterator),就是传统的for(xxx) {iterator}的升华.把循环和操作给解耦.
其次,那个[context]引起了我的注意.看上去很高深的样子,经过google后,原来是调用了Call,而Call是什么?
就是调用方法时换掉对象环境,相当于面象对象的虚方法.但实际上更巧妙.原因是面向对象不能这么用.强类型啊.
这样,其实就变成了三个的组合,道生一,一个函数接口比如each, 一生二,高阶函数each(list, iterator),二生三,(list, iterator,[context]), 三生万物.这三个组合,可以千变万化.可见中国人有多聪明,早在5000年前就明白这些道理.可惜中国传统文化,被错误的政治课本代替了.他们告诉我那些课本上的东西是对的,是真理,但是本人就是听不懂,也无法用逻辑去推理出来,只能被动接受,你说是对的那就是对的吧.但是涉及到编程,还是得使用其它的知识.
然后顺便再提下,$, 这个也是符合道的思想的东西.$为一,$(集合)为二,$(集合).操作为三,然后就千变万化了,其实和_是一样一样的,只不过写法略有不同.我们对比一下
[context].$(list).iterator 注意[context]这个上下文环境是可以递归的.这就分形的自相似性.
_.(list, iterator, [context]) 注意,所有的参数都是可以递归的,这就是分形的自相似性,但是_明显灵活性更高.而$的iterator受限了.你不能通过函数式的方法去用它,可见$是一个函数式应用的实例,它是个工具,库,框架,而_是真正的函数式,是个规则.
搞清楚了基本概念,再往下就容易多了.
映射:map_.map(list, iterator, [context])
Alias: collect
化简:reduce_.reduce(list, iterator, memo, [context])
Aliases: inject, foldl
var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); //注意这里的memo其实就是个初始化值,观察原代码,memo是不可以省略的. => 6
reduceRight 略过
查找:find_.find(list, iterator, [context])
Alias: detect //只返回符合条件的第一个,相当于SingleOrDefault
过滤:filter_.filter(list, iterator, [context])
Alias: select //返回符合条件的集合
条件:where_.where(list, properties)
这里where的条件变了,用我们已有的常识来推理下,where需要多种条件组合,我们自已可能这么干,定义一个查询条件表达式,查询是key, value, 比较符,连接符.比如:
name = '量子计算机' and (评论数 > 10 or 阅读数 > 1000) 我们看看它的properties怎么干的.
实际上_的where没那么复杂,就是把包含key,value的properties的结果返回一个集合.其实就是只有"等于","和" 两种默认比较符,我们看下代码是否如此.
恩,代码暴露了一切,_没有想象那么复杂,这里是前端,轻量级的,没有后端大量的复杂业务逻辑,也没有大量的条件,异常判断什么的,也没有重载符,所以where是相当于重载了filter.
单结果条件:findWhere_.findWhere(list, properties) 相当于重载了find
拒绝(抛弃):reject_.reject(list, iterator, [context]) 相当于filter取反
下面三个都是逻辑运算,返回值是true或false, 相当于 and or in
全部:every_.every(list, iterator, [context])
Alias: all
部分:some_.some(list, [iterator], [context])
Alias: any
包含:contains_.contains(list, value)
Alias: include