underscore源码解读:Array Functions 相关源码拾遗和小结

606 查看

Main

很快,Array Functions 部分到了尾声,今天来做个了(xiao)结。

underscore 给数组(以及 arguments,这里特别说明下,underscore 的数组扩展方法,同样适用于 arguments)增加了 20 个扩展方法,值得一提的是,很多有意思的方法,比如 map,shuffle 等,都被放在了 Collection Functions 中。本文来看看 Array Functions 中还有哪些有意思的方法(之前没有被提及)。

_.compact

这个方法很有意思,它的作用是剔除数组中的假值,返回数组副本。

实现非常的简单:

_.filter 我们在以后会讲到,这里你可以把它理解为 Array.prototype.filter 的一个 polyfill,来看看 _.identity 是个什么东东。

乍一看,_.identity 似乎没什么卵用,传入一个参数,原封不动返回这个参数,什么鬼?而再看 _.compact 的实现,就会发现非常巧妙!细细品味下,直接过滤了数组的假值,而 _.identity 在源码中能在多个地方复用。

从这个方法可以想到 PHP 的 array_filter 函数。array_filter 的基本用法和 Array.prototype.filter 相似,都是为了过滤数组中的元素。

但是,值得注意的是:

If no callback is supplied, all entries of array equal to FALSE (see converting to boolean) will be removed.

这就有点 6 了,直接把 _.filter 和 _.compact 两个方法合二为一了。

Array.prototype.filter 为何不设计成这样呢?没有 callback 传入的时候,直接过滤假值…

_.difference & _.without

先来看 _.without,它的作用是从数组中剔除指定的元素。

恩,没错,剔除数组 a 中的 value 为 1, 2, 3 的元素,这个过程中用 === 来进行比较。该方法传入的第一个参数是数组,后面的参数为单个元素。

而 _.difference 呢?和 _.without 的唯一区别是,第二个参数开始传入的是数组。(分别和数组中的元素比较)

从 a 数组中剔除 1,2,3,5,6。

仔细一想,如果已经实现了 _.difference,我们把 _.without 的参数放入数组,然后传入 _.difference 就 ok 了!倒过来就不行了(思考下为什么)。

来看 _.difference 的实现,非常简单:

不熟悉 flatten 的可以看看 前文,当 shallow 和 strict 均为 true 时,展开一层,并且过滤非数组元素,即可以起到将多个数组合并的作用。之后利用 ._filter 进行过滤即可。

而 _.without 方法则建立在 _.difference 基础上。

总结

数组的扩展方法就解读到这里了,相关源码可以参考 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L450-L693 这部分。接下去要解读的是 Collection Functions 部分,所谓 Collection,正是 Object & Array,也就是说这部分方法既可以用于 Object 也能用于 Array,比如我们熟悉的 map,filter,shuffle 等等,都在这部分内。

放个预告,下一篇会暂缓下 Collection Functions,讲下 array-like 相关的东西,敬请期待。

PS:坚持一件事真的挺难,一个月来,每天坚持看点源码,几乎把所有业余时间花在了上面,写了 10 篇随笔,每篇文章写的时间不短,关键还需要构思,如何提炼出一个主题,如何写让人看了会有所收获,恩,继续坚持。请关注我的 Repo https://github.com/hanzichi/underscore-analysis 支持我~