欢迎各位兄弟 发布技术文章
这里的技术是共享的
效果如图
使用 Underscore 的 chain 方法,可以返回一个包装的对象,这个对象里面包含着 Underscore 里面的所有的方法,也就是我们可以直接调用这些方法,完成以后,还会返回这个包装后的对象,这样我们可以继续去调用 Underscore 的方法,这就是链式调用。
现在这里有一个 albums 数组 ... 下面,我们先用 chain 方法去包装一下它 ...
_.chain(albums)
给我们返回来一个包装后的对象 ... 在 _wrapped 属性里面,就是包装的原来的数据 ... __proto__ 里面就是 Underscore 的方法 ...
下面,我们先调用一个 sortBy 这个方法,去给包装后的数据排下顺序,排序的条件,可以使用 releaseYear 这个属性的值 ...
_.chain(albums).sortBy('releaseYear')
回车 .. 返回的还是一个包装后的数据 ... 我们可以继续去调用方法处理它 ...
这里,再用一个 first() 方法,得到排序后的第一个结果 ...
现在,_wrapped 里面,就只剩下 继续革命 这个专辑项目了 ... 因为它是排序之后的第一个结果 ...
下面我们学习几个在 Underscore 里面跟对象相关的一些方法。
keys 这方法可以得到一个对象里面的所有的属性的名字 ... 比如要得到 album 这个对象里的属性名称列表 .. 可以把这个对象作为 keys 方法的一个参数 ...
_.keys(album)
返回的结果是一个数组,数组里面的项目就是在 album 这个对象里面的每个属性的名字 ...
values
如果你想要的是对象里面的所有的属性的值,可以使用 values 方法 ...
_.values(album)
它也会返回一个数组,数组里面的项目就是在 albums 这个对象里面的属性的值 ...
pick
如果你只想要对象里面的指定的几个属性 ... 可以使用 pick 方法去挑选一下 ... 要挑选的是 album 这个对象 ... 然后再去指定一个想要的属性的列表 .. 这里我们只想要的是 title ,还有 artist 这两个属性 ..
_.pick(album, 'title', 'artist')
返回的结果是一个对象,在这个对象里面,会包含我们挑选的几个属性 ...
omit
有时候,我们可能需要有的函数只能被执行一次,比如用这样的函数去初始化一些东西。
创建这样的函数,可以使用 Underscore 的 once 这个方法。
现在我们这里有一个函数叫 fireIntheHole ... 想让它只能被执行一回 ... 用 once 去处理一下 ... 可以给这个一次性的版本的函数起个新名字 .. 叫它 fire ...
var fire = _.once(fireIntheHole)
保存 ... 回到浏览器 .
在控制台上,先执行一次 fire ...
会显示 bomm ...
然后再执行一下它 ...
会返回 undefined ... 再执行 ... 还是会返回 undefined ...
因为 fire 是一次性的函数,才能被执行一回 ...
一个函数在执行以后,再次执行它的时候,你可以设置一下两次执行间隔的时间。这就是 Undersocre 的 throttle 的功能。
比如这里我们有一个函数 ... fireIntheHole ... 我们打算让程序在每次执行这个函数的时候,必须间隔一段时间才行 ... 可以使用 throttle 去处理一下它 ...
可以给这个防止滥用版本的函数起个新名字 ... 叫它 fire ... 然后用 throttle ... 第一个参数是要处理的函数的名字 ... 这里就是 fireIntheHole ... 第二个参数是等待的时间,也就是两次执行这个函数中间隔的时间 ... 单位是毫秒 ... 这里设置成 3000 毫秒 ...
var fire = _.throttle(fireIntheHole, 3000);
这样执行 fire 之后 ... 才次再想去执行 fire ,只有等待 3 秒以后才行。
保存 ...
到浏览器上试试 ...
先执行一次 fire ... 然后再继续去执行它 ... 你会发现,第一次执行以后,再次执行它的时候,只有等待一会儿,才会起作用。
程序里面可能会有一些函数要做比较复杂的运算,我们可以让这些运算都完成以后再去执行这个函数。这样,不会影响到程序继续去执行其它的代码。
比如这里我们有一个函数 fireIntheHole ... 它做的事就是在控制台上输出 bomm.. bomm.. boom...
在这个函数的下面, 还有一个叫 run 的参数 ... 它会在控制台上输出 捂上耳朵,狂奔!这几个字儿 ...
在下面,我们先去执行一下 fireIntheHole .... 接着去执行 run 这个函数 ...
回到浏览器 .... 刷新一下 ..
你会看到,控制台上先会显示在 fireIntheHole 里面的 boom ... bomm... bomm ...
然后才会执行 run ,捂上耳朵,狂奔!
这时候人已经完了,对吧。
下面,我们去改造一下 ...
用 defer 方法,去处理这个 fireIntheHole 这个函数 ...
_.defer(fireIntheHole);
保存 ... 再回到浏览器 ... 刷新一下 ...
这次,你会看到,先会去执行 run 函数 ... 这时候人已经跑远了 ...
通常调用函数以后,会立即执行这个函数。使用 Underscore 的 delay 方法, 我们可以延时去执行函数 ...
先在控制台上,直接定义一个函数 .. 可以叫它 fireIntheHole ... 这个函数能做的事,就是在控制台上输出 Bommmm
var fireIntheHole = function() { console.log('Boommm...'); };
先去执行一下这个函数 ... 输入 fireIntheHole ...
会在控制台上立即输出 Bommmm ... 人还没跑远呢手雷就炸了 ...
下面,我们可以使用 delay 去延时执行这个函数 ...
_.delay ... 它的第一个参数是要延时执行的函数 ... 这里就是 fireIntheHole ... 然后第二个参数要延迟的时间 ... 单位是毫秒 .. 1000 毫秒就是 1 秒 .. 这里我们设置成 3000 ,表示三秒以后去执行这个函数 ..
另外,还可以给这个方法添加第三个参数,也就是要传递给函数的参数的值 ...
_.delay(fireIntheHole, 3000)
bindAll 这个方法可以把一些方法绑定到一个对象上面,这样在执行这个方法的时候, 在这些方法里面,this 这个关键词表示的就是跟这些方法绑定到一块儿的那个对象。下面,我们再通过一个演示来理解一下 bindAll 的作用。
先打开 index.html 这个文档 ...
div.container>h1.page-header{bindAll}+button.btn.btn-default.btn-lg*2
在这上面添加两个按钮 .. 一个是播放按钮 ... 上面可以添加一个 id 叫做 play ... 再添加一些其它的 css 类,这些类的样式是在 bootstrap 这个框架里面定义的。
再添加一个 暂停 按钮 .. 上面添加一个叫 pause 的 id ...
在这一章里,我们去学几个 Underscore 里面的跟函数相关的方法。
bind
先来看一下 bind 这个方法。bind 这个词有绑定的意思,你可能在其它的地方也看到过这个词,比如在 jQuery 里面,它的意思就是去绑定事件。不过在 Underscore 这个上下文里面,bind 的意思是为函数绑定一个对象。这样在调用这个函数的时候,在函数的内部,this 这个关键词表示的就是这个对象。
下面,我们去试一下这个方法 ... 先定义一个函数 ... 可以使用函数表达式的方法去定义这个函数 .. (#编辑器) ..
给这个函数起个名字 .. 叫做 nowPlaying ... function ... 在这个函数里面,让它 返回 this 这个关键词 ...
var nowPlaying = function() { return this; }
在下面,我们再去调用这个函数 ...
nowPlaying()
你会发现,这个函数会返回 Window 这个对象 .. 也就是,在这个函数里面,this 这个关键词表示的是 Window 这个对象 ...
我们这里有一个 album 对象 ... (#album)
sortedIndex 这个方法,可以返回即将要插入到数组里面的项目,在这个数组里面的位置是什么,也就是它的索引号是什么。
foods 是一个数组,我们用 sortBy 对它进行了排序,并且把排序之后的结果交给 sortedFoods 这个变量 ...
下面我们可以用 sortedIndex ,去测试一个要插入到这个数组里的项目的位置。
_.sortedIndex ... 第一个参数是要测试的数组 ... 这里就是 sortedFoods ... 第二个参数是要测试的值 ... 我们可以试试 cookie 这个项目如果插入到 sortedFoods 里面它的位置会是什么 ...
_.sortedIndex(sortedFoods, 'cookie')
返回的结果是 2 ,意思就是,如果把 cookie 作为 sortedFoods 里面的一个项目的话,如果保存排序的方式不变,它的位置是 2 ,也就是它会排在 bread 的后面 ...
下面, 我们可以验证一下 ...
先把 cookie push 到 foods 这个数组里面 ...
foods.push('cookie')
然后再对 foods 重新排下顺序 ..
想要得到在一个数组里面,某个值的项目第一次出现的位置,用的是 indexOf 这个方法。找出某个值在数组里面最后一次出现的位置,可以使用 lastIndexOf ...
这里我们有一个叫 newFoods 的数组 ... 下面,我们用 indexOf 去找出,apple 这个值的项目第一次出现在这个数组里面的位置号。
indexOf ... 先给它指定一个数组参数 .... newFoods ... 它的第二个参数是要判断位置的项目的值 .. 这里就是 apple ...
_.indexOf(newFoods, 'apple')
返回的结果是 2 .... 在 newFoods 这个数组里面,第一次出现 apple 这个项目的位置是 2 ... 这个位置号或者叫索引号是从 0 开始的 ...
如果要找的值不在这个数组里面,这个方法会返回 -1 ...
lastIndexOf
想找出最后一次出现 apple 这个项目的位置号 .. 可以使用 lastIndexOf ...
_.lastIndexOf(newFoods, 'apple')
使用 uniq 这个方法,可以去掉在数组里面重复出现的项目。
我们可以先把这里的 fruits 还有 foods 这两个数组合并到一块儿 ... 先合并之后的结果起个名字 ... 可以叫它 newFoods ...
合并数组可以使用 concat 这个方法 ... 这是 JavaScript 原生自带的一个方法 ...
var newFoods = fruits.concat(foods)
再查看一下这个合并之后的 newFoods ...
这个数组里面,会出现一个重复的项目,也就是这个 apple ... 下面再用一个 Underscore 的 uniq 方法,去掉数组里面的重复的项目。
_.uniq(newFoods)
在返回的结果里面,去掉了重复出现的 apple ,只有保留其中的一个。
把几个数组合并到一块儿,去掉重复的项目,得到的就是两个数组的并集。可以使用 union 这个方法。现在,我们这里有两个数组,fruits,还有 foods ... 下面用 union 方法,得到这两个数组的并集 ..
union ... fruits 逗号 ... foods .. 如果有其它的数组,可以继续用逗号分隔一下,再添加进来 ..
_.union(fruits, foods)
得到的结果就是,fruits 和 foods 这两个数组的并集 ... 注意这两个数组里面,都有 apple 这个项目 ... 同并集以后,只会保留一个 apple ...
intersection
如果想要得到的是数组之间的交集 .. 要用的是 intersection 方法 ..
_.intersection(fruits, foods)
返回的结果是 apple ... 因为在这两个数组里面,共有的项目只有 apple ...
difference
要得到一个数组跟其它数组的差集,也就是在这个数组里面有的,在其它数组里没有的项目 ... 可以使用 difference ...
_.difference(fruits, foods)
我们可以按照自己设置的条件,把一个数组分割成两个部分,一部分是满足条件的项目,另一个部分是不符合条件的项目。要用到的方法是 Underscore 的 partition ...
现在这里有一个 albums 数组,里面有几个项目 ... 我们可以把这分割成两个部分,一部分是 releaseYear 是 1992 年的专辑 ... 另一部分就是 releaseYear 不是 1992 年的专辑项目 ...
partition ... 先指定一下要分割的数组 ... 这里就是 albums ... 然后再设置一下条件,可以用一个函数返回这个条件 ... 用 album 表示数组里面的每个项目 ... 然后 return ... 返回的是 album 的 releaseYear 属性的值,等于 1992 ...
_.partition(albums, function(album){ return album.releaseYear === 1992; })
返回的结果就是一个大的数组,里面分成了两小部分,第个部分又是一个数组 ... 第一部分是符合条件的项目 ... 你会看到,这个项目的 releaseYear 属性的值是 1992 ...
在这一章里,我们学一下 Undersocre 里面跟数组相关的函数。
现在,这里有一个叫 tracks 的数组 ... 如果想得到这个数组里面的头一个,或者头几个项目,可以使用 frist 这个方法。
_.first(tracks)
返回的就是第一个项目,长城 ... 想得到头两个项目,可以给 first 这个方法传递一个数字参数 ... 得到头两个项目,就把这个参数设置成 2 ...
_.first(tracks, 2)
得到的就是,tracks 这个数组里面的头两个项目 ...
last
想得到最后一个或者最后几个项目,用的是 last 这个方法 ...
_.last(tracks)
返回的就是 tracks 数组里面的最后后一个项目,早班火车 .. 要返回后几个项目,可以给这个方法传递一个数字参数 ... 比如要返回后两个项目,就把这个参数的值设置成 2 ..
_.last(tracks, 2)
initial
initial 这个方法返回的是数组里面除了最后一个项目的其它的项目。
_.initial(tracks)
对一个列表进行随机处理,也就是把列表里面的项目的顺序打乱,得到一个新的列表 ... 这个功能我们可以使用 shuffle 。 在一个列表里面,取出几个样本,可以使用 sample 方法。
(#tracks)
先试一下 shuffle ... 把要随机处理的列表交给这个方法 ...
_.shuffle(tracks)
回车 ... 你会发现,新得到的这个列表里面的项目的顺序,跟以前是不一样的 ... 再用这个方法处理一下 tracks 这个数组 ...
又会得到一个新的顺序的列表 ...
sample
下面,我们再去试一下 smaple 这个方法 ... 同样把 tracks 这个数组交给这个方法去处理一下 ...
_.sample(tracks)
这个方法,会随机从指定的列表里面取出一个样本 ... 再执行一次 ..
又会随机取出一个样本 ... 我们也可以去指定每一次取出的样本的数量 ...
_.sample(tracks, 2)
这次会从 tracks 里面,随机取出两个样本 ...
我们可以先对一个列表按照自己设置的标准分一下组,然后得到每个小组里的项目的数量 ... 这就是 countBy 方法的功能。它有点像是前面介绍过的 groupBy ... 不同的是 ... groupBy 返回的是分组以后的项目 ... countBy 返回的是分组之后的项目的数量。
(#albums)
我们可以看一下 albums 这个列表 .. 比如我们想要得到在这个列表里面,artist 这个属性的值是 Beyond 的项目一共有多少个 .. 值是 Coldplay 的项目一共有多少 ...
countBy ... 要分组统计的是 albums ... 再给它一个迭代器 ... 在它里面要返回要分组的属性 ...
_.countBy(albums, function(album){ return album.artist; })
回车 ... 返回的结果是一个对象 ... 这个对象里有两个属性 .. 表示按照 artist 属性的值,把列表分成了两个组 ... 其中值是 Beyond 的项目一共有两个 ... artist 的值是 Colplay 的项目一共有一个。
groupBy 这个方法,可以对一个列表,用某种方式进行分组 ... 比如这里有一个叫 fruits 的数组 ... 里面是一些水果的英文名字 ... 下面,我们可以使用 groupBy ,按照项目的字符数去分一下组 ...
_.groupBy ... 要分组的列表是 fruits ... 然后再指定一下按照什么标准去分组,这里可以使用一个迭代器,也可以直接使用属性的名字 .. 我们用一个 length 属性,它表示项目的字符长度 ...
_.groupBy(fruits, 'length')
返回的是一个对象 ... 这个对象里面有几个属性 ... 属性名是 4 的这个项目里面,包含一个 pear ... 这个数字 4 实际上就是 fruits 这个列表里面的项目的字符串的长度 ... 也就是,在这个列表里面,所有的长度是 4 的项目,都会在这里面 ... 因为在 fruits 里面,只有 pear 是 4 个字符 .. 所以这个小组里面,只有一个 pear ..
下面还有一个 5 .. 里面有 apple 这个项目 ... 最后还有一个 6 ,这里面有两个项目 ... orange ,还有 apple ..