欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Underscore 基础

1)介绍


在 Underscore 里面,提供了非常多,而且非常实用的一些函数去处理数据。比如你可以用一个函数去处理一个数组或对象里面的每一个项目,你可以查找,过滤数据,可以对数据进行排序还有分组,可以找出两组数据之间的不同的地方,或者相交的地方,你可以去掉数据列表里面的重复的东西。

Underscore 还提供了一些跟函数相关的方法,比如我们可以把一些方法跟对象绑定到一起,这样在方法里面,可以使用对象里面的属性,我们还可以延时去执行函数,可以防止滥用函数,可以创建一次性的函数。

最后,我们再看一下 Underscore 里的链式调用。

来自 http://ninghao.net/video/1480#info

2) 准备

下面我们先介绍一下这个课程里用到的东西,你可以在课程的资源包里,找到一个启动项目 ... 用 Bracks 编辑器打开这个项目目录,就是你现在看到的这个样子 ..

index.html 是项目的主页 ... 在这个文档上,用到了 bootstrap 框架的样式表 ... 还有 jquery ... underscore.js ... 这是 underscore 库的文件 ...

下面的 data.js ... 在 js 这个目录的下面 ... 在这个文件里面,事先定义好了一些要在这个课程里面用到的数据 ... 一些数组还有对象 ...

最后的 app.js ,是一个空白的脚本文件 ... 在课程里面,我们可能需要在它里面去输入几行代码 ...

这个课程的大部分的测试,都是在 Chrome 浏览器的控制台上完成的 ...

在浏览器里,打开这个 index.html ...

打开控制台,可以点击 视图 菜单 .. 开发者 ... 选择 JavaScript 控制台 ... 或者也可以直接使用快捷键 alt + command + J 打开控制台。

windows 上应该是 alt + ctrl + J

点击 右上角 的这个按钮 ... 可以在新窗口打开控制台 ...

再点击这个按钮 ... 会回到原来的样式 ...

在控制台,输入在 data.js 里面定义好的数据,可以直接输出里面的内容 ... 比如输入 fruits ... 会返回在 fruits 里面的东西 ...

来自 http://ninghao.net/video/1481#info

 
集合
3) 集合 - 循环处理列表中的每一个项目 - each

如果你想循环去处理一个列表,比如一个数组,或者一个对象。可以使用 Underscore 的 each 方法 ... 这个方法有两个参数,第一个参数是要处理的列表,第二个参数是一个迭代器。each 方法会把列表里面的每一个项目,都交给这个迭代器去处理一下 ...

如果列表是一个数组的话,这个迭代器接收的参数就是 element ,表示当前这次处理的元素 ... 第二个参数是 index,表示这个元素在数组里面的索引号 .. 最后一个参数是 list ,表示这个列表本身。

如果要处理的列表是个对象的话,这个遍历器的第一个参数是对象的值,可以用 value 表示 ... 第二个参数是 key ,表示对象里的属性的名字 .. 最后一个参数是 list ,表示要处理的这个列表对象。

下面, 我们去试一下这个方法 ...

先处理一下 tracks 这个数组 ... 要做的事就是,在控制台上输出这个数组里面的每个项目的索引号,还有对应的值 ... underscore 点 each ,使用 underscore 的 each 这个方法 ... 要处理的列表是 tracks ... 再设置一下处理这个列表的函数,也就是遍历器 ...

可以使用一个函数的名字 ... 这里我们直接使用一个匿名函数 ... 给它两个参数,用 track 来表示当前要处理的元素 ... 然后再用 index 表示元素的索引号 ...

在这个函数里面,用一个 console.log ,在控制台上输出 tracks 里面的项目的索引号,还有对应的值 ...

_.each(tracks, function(track, index){ console.log(index + ' ' + track);})

回车 ... 你会看到这里每一行会输出 tracks 数组里面的一个项目的索引号还有值 ... 注意在最后,这个方法会返回处理的这个列表 ...

这个方法还有一个别名,叫 forEach ...

_.forEach(tracks, function(track, index){ console.log(index + ' ' + track);})

这两个方法的效果是一样的 ...

对象

下面,我们再用 each 这个方法去遍历一个对象 ... 整理一下屏幕 ... command + K 清空一下 ... 或者 command + R 刷新一下页面 ...

要处理的对象是 album ... (#输入 album)

下划线 ... 点 each ... 要遍历的列表是 album 这个对象 ... 再定义一下遍历器 ... 用一个匿名函数 .. . 处理对象的时候,第一个参数是对象的属性的值,这里我们用 value 表示 ... 逗号分隔一下 ... 第二个参数是对象的属性的名字 .. 可以用 key 来表示 ...

在这个函数里面,我们把 album 这个对象里的属性名字还有对应的值输出到控制台上 ...

_.each(album, function(value, key){ console.log(key + ':' + value); })

回车 ... 在控制台上,每一行显示 album 这个对象里面的一个属性 ... 包括属性的名字,还有对应的值 ...

在最后,会返回这个被遍历的对象 ...

来自  http://ninghao.net/video/1482#info

 
4)遍历列表项目生成新的处理之后的列表 - map

遍历列表里面的每一个项目映射到一个迭代器里面去处理,然后返回一个新的处理之后的列表。这就是 map 这个方法的功能。它的用法跟上个视频里介绍的 each 方法差不多 ...

下面,我们用 map 再去处理一下 tracks 这个数组 ... 比如我们要给这个数组里面的每一个项目的值都添加一个书名号 ...

_.map ... 指定一下要遍历的列表 ... 这里就是 tracks 这个数组 ... 然后再设置一下,迭代器,或者叫循环处理器 ... 其实就是一个处理列表里面的项目的函数 ... 这里我用一个匿名函数 ...

然后用 track 表示当前要处理的列表里面的项目 ... 你可以根据自己的需求去命名这个参数。

在这个函数里面,返回处理之后的结果 .. . 用一个 return ... 一个书名号 .. 加上 track ... 表示当前这个项目 ... 后面再加上书名号的另一部分 ...

_.map(tracks, function(track) { return '《 ' + track + ' 》';})

回车 ...

会给我们返回处理之后生成的新的列表 ... 在这个数组里面,每一个项目的值的周围都会有一组书名号 ...

这个方法也有个别名,叫 collect ...

_.collect(tracks, function(track) { return '《 ' + track + ' 》';})

得到的是一样的结果 ...

来自 http://ninghao.net/video/1483#info

 
5)把列表里的所有值转换成一个值 - reduce

Underscore 里面的 reduce 方法,可以把一个列表里面的所有的值,用你想要的方法换算成一个值。比如一个数字列表,你可以得到它们彼此相加的结果。

下面,我们使用这个方法去处理一下 numbers 这个数组 ... 让这个数组里的值彼此相加,返回这个相加之后的结果 ...

这个方法的第一个参数是要处理的列表,第二个参数是遍历器,或者叫迭代器,循环处理器 .. 第三个参数是存储结果的一个初始的状态 ... 最后有一个可选的 context 参数。

_.reduce ... 先指定一下要处理的列表 .. 这里就是 numbers 这个数组 .. 第二个参数是迭代器 ... 用一个匿名函数 ... 第三个参数是存储结果的初始状态 ... 这里我们设置成 0 ...

在这个迭代器函数里面支持几个参数 ... 第一个参数表示当前结果,一般用 memo 来表示,第二个参数表示本次循环的列表里面的值 .. 第三个参数是 index ,如果处理的列表是个对象的话,这个参数就应该是 key ,最后一个参数表示列表本身 ...

这里我们只需要两个参数 .. memo 还有 number ... number 列表 numbers 里面的一个数字。

然后在这个函数里面,返回处理的结果 ... return ... 用 memo 再加上 number ...

_.reduce(numbers, function(memo, number){ return memo + number; }, 0)

回车 ... 得到的结果是 10 ... 迭代器首先会处理 numbers 里面的第一个项目,也就是数字 3 ,存储的结果的初始状态是 0 ,要处理的动作就是,让 memo 加上 number ,第一次就应该是 0 加上 3 ... 结果是 3 ...

然后继续第二次循环 .. 这里的 memo 就是上一次处理的结果,也就是 0 + 3 算出来的结果 .. number 表示列表里面的第二个项目 ... 也就是数字 6 ... 然后用 3 加上 6 .. 再返回这个结果 ... 现在 memo 的值,就会是 9 了 ...

继续执行 ... 9 加上 numbers 里面的最后一个数字 1 ,结果就是这里显示的出来的数字 10 ...

对象

下面,我们再用这个方法去处理一个对象的属性 ... 先清理一下屏幕 .. command + K

要处理的对象是 album ... (#输入 album 回车)

要做的就是,把这个对象里的属性的名字和值连接到一块 ... 属性和名字之间用一个冒号 ... 不同的属性之间使用一个分号 ...

_.reduce ... 要处理的东西是 album ... 设置一下处理器 ... 用一个匿名函数 ... memo 的初始值设置成一个空白的字符串 ...

这个处理器要接受 memo 参数,还有 value 和 key 参数,value 表示对象属性的值,key 表示对象属性的名字 ...

在这个处理器里面,返回 memo ,也就是当前存储结果 ... 加上对象属性的名字 ... 再连接一个冒号 ... 然后是属性的值 ... 用 value 表示 ... 最后是一个分号 ..

_.reduce(album, function(memo, value, key){ return memo + key + ':' + value + ';';}, '' )

回车 ...

得到的结果就是用我们设置的形式连接的对象里面的属性 ... 属性名和值之间有一个冒号,不同属性之间有一个分号 ..

来自  http://ninghao.net/video/1484#info

 
6)查找,过滤,反过滤 - find, filter, reject

使用 find 这个方法,可以去找到列表里面第一个符合我们设置的规则的结果。下面,去试一下 ..

比如这个 tracks 数组 .. 找出这个数组里面的元素的字符长度大于 2 的第一个项目 ... _.find ... 要查找的列表是 tracks ... 再设置一下它的第二个参数,是一个函数 ... 在这个函数里面,我们可以去设置一下查找的规则 ...

这里我们让它返回元素字符长度大于 2 的第一个项目 ...

_.find(tracks, function(track){ return track.length > 2; })
// "不可一世"

回车 ... 返回的结果是 不可一世 ... 因为在 tracks 这个数组里面,第一个字符长度大于 2 的项目就是这个 不可一世 ... 如果你想得到所有的符合设置的规则的项目 ...

可以使用 filter 这个方法 ...

_.filter(tracks, function(track){ return track.length > 2; })
// ["不可一世", "温暖的家乡", "无语问苍天", "早班火车"]

返回的结果就是在 tracks 这个数组里面,所有的字符长度大于 2 的项目 ... filter 是过滤的意思 ... 这个方法的意思就是,过滤出符合规则的结果 ... 也就是,在这个函数里面,所有通过验证的项目都会包含在这个返回来的结果里面。

跟 filter 相反的是 reject ... 使用它,我们可以得到所有的验证失败的项目 ...

_.reject(tracks, function(track){ return track.length > 2; })
// ["长城", "农民", "遥望"]

得到的结果是,tracks 里面,所有的字符数小于 2 的项目 ...

来自  http://ninghao.net/video/1485#info

 
7)找到包含特定属性和值的项目 - where, findWhere

要找出包含某些属性还有对应的值的项目,可以使用 where 这个方法。 现在你看到的 albums 是一个数组,数组里面的每一个项目都是一个对象 ... 对象的内容表示某张音乐专辑 ...

比如我们要找到 artist 属性的值是 Beyond 的项目 ... 输入 _.where ... 指定一下要查找的列表 ... 这里就是 albums ... 第二个参数是要查找的属性还有对应的值 ... 它是一个对象 ... 属性是 artist ... 值是 Beyond ...

_.where(albums, {artist: 'Beyond'})

回车 ... 得到的结果就是包含 artist 这个属性并且它的值是 Beyond 的项目 ... 我们也可以查找多个属性还有对应的值 ... 比如要找到 artist 属性的值是 Beyond ,还有 releaseYear 是 1992 的项目 ...

在这个要找的属性里面,再加上一个 releaseYear ... 值是 1992

_.where(albums, {artist: 'Beyond', releaseYear: 1992})

这次只给我们返回一个项目 ... 因为只有它里面的 artist 属性的值是 Beyond,releaseYear 的值是 1992 ...

findWhere

如果只想找到第一个包含特定属性和值的项目 .. 可以使用 findWhere 这个方法 ...

_.findWhere(albums, {artist: 'Beyond'})

返回的就是第一个包含 artist 属性并且值是 Beyond 的项目 .. .

来自 http://ninghao.net/video/1486#info

 
8)判断列表里的项目 - every, some, contains
 
9)挑出列表里面的指定属性的值 - pluck
 
10)找出列表里面值最大或最小的项目 - max, min
 
11)排序 - sortBy
 
12)分组 - groupBy
 
13)分组计数 - countBy
 
14)随机与取样 - shuffle, sample
 
数组
15)数组 - 从数组里挑选项目 - first, last, initial, rest, without
 
16)把数组分割成两部分 - partition
 
17_并集,交集,差集 - union, intersection, difference
 
18)去掉数组里面的重复的项目 - uniq
 
19)找出指定值的项目在数组中的位置 - indexOf, lastIndexOf
 
20)测试即将插入到数组里的项目的位置 - sortedIndex
 
函数
21)函数 - 为函数绑定对象 - bind
 
22)把对象里的一些方法绑定到对象上 - bindAll
 
23)延时执行函数 - delay
 
24)你继续,我先等会儿 - defer
 
25)防止滥用- throttle
 
26)只能执行一次的函数 - once
 
其它
27)对象 - keys, values, pick, omit
 
28)链式调用 - chain
 
普通分类: