【跟着子迟品 underscore】Array Functions 相关源码拾遗 & 小结
Why underscore
最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中。
阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多。为什么是 underscore?最主要的原因是 underscore 简短精悍(约 1.5k 行),封装了 100 多个有用的方法,耦合度低,非常适合逐个方法阅读,适合楼主这样的 JavaScript 初学者。从中,你不仅可以学到用 void 0 代替 undefined 避免 undefined 被重写等一些小技巧 ,也可以学到变量类型判断、函数节流&函数去抖等常用的方法,还可以学到很多浏览器兼容的 hack,更可以学到作者的整体设计思路以及 API 设计的原理(向后兼容)。
之后楼主会写一系列的文章跟大家分享在源码阅读中学习到的知识。
- underscore-1.8.3 源码解读项目地址 https://github.com/hanzichi/underscore-analysis
- underscore-1.8.3 源码全文注释 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/underscore-1.8.3-analysis.js
- underscore-1.8.3 源码解读系列文章 https://github.com/hanzichi/underscore-analysis/issues
欢迎围观~ (如果有兴趣,欢迎 star & watch~)您的关注是楼主继续写作的动力
Main
很快,Array Functions 部分到了尾声,今天来做个了(xiao)结。
underscore 给数组(以及 arguments,这里特别说明下,underscore 的数组扩展方法,同样适用于 arguments)增加了 20 个扩展方法,值得一提的是,很多有意思的方法,比如 map,shuffle 等,都被放在了 Collection Functions 中。本文来看看 Array Functions 中还有哪些有意思的方法(之前没有被提及)。
_.compact
这个方法很有意思,它的作用是剔除数组中的假值,返回数组副本。
实现非常的简单:
_.compact = function(array) {
return _.filter(array, _.identity);
};
_.filter 我们在以后会讲到,这里你可以把它理解为 Array.prototype.filter 的一个 polyfill,来看看 _.identity 是个什么东东。
_.identity = function(value) {
return value;
};
乍一看,_.identity 似乎没什么卵用,传入一个参数,原封不动返回这个参数,什么鬼?而再看 _.compact 的实现,就会发现非常巧妙!细细品味下,直接过滤了数组的假值,而 _.identity 在源码中能在多个地方复用。
从这个方法可以想到 PHP 的 array_filter 函数。array_filter 的基本用法和 Array.prototype.filter 相似,都是为了过滤数组中的元素。
function isOdd($num) {
return $num & 1;
}
$a = Array(1, 2, 3);
$a = array_filter($a, 'isOdd');
var_dump($a);
// array
// 0 => int 1
// 2 => int 3
但是,值得注意的是:
If no callback is supplied, all entries of array equal to FALSE (see converting to boolean) will be removed.
这就有点 6 了,直接把 _.filter 和 _.compact 两个方法合二为一了。
$a = Array(0, 1, 2, 3, null, false, 4);
$a = array_filter($a);
var_dump($a);
// array
// 1 => int 1
// 2 => int 2
// 3 => int 3
// 6 => int 4
Array.prototype.filter 为何不设计成这样呢?没有 callback 传入的时候,直接过滤假值...
_.difference & _.without
先来看 _.without,它的作用是从数组中剔除指定的元素。
var a = [1, 2, 3, 4, 5];
var ans = _.without(a, 1, 2, 3);
console.log(ans); // [4, 5]
恩,没错,剔除数组 a 中的 value 为 1, 2, 3 的元素,这个过程中用 === 来进行比较。该方法传入的第一个参数是数组,后面的参数为单个元素。
而 _.difference 呢?和 _.without 的唯一区别是,第二个参数开始传入的是数组。(分别和数组中的元素比较)
var a = [1, 2, 3, 4, 5];
var ans = _.difference(a, [1, 2, 3], [5, 6]);
console.log(ans); // [4]
从 a 数组中剔除 1,2,3,5,6。
仔细一想,如果已经实现了 _.difference,我们把 _.without 的参数放入数组,然后传入 _.difference 就 ok 了!倒过来就不行了(思考下为什么)。
来看 _.difference 的实现,非常简单:
// _.difference(array, *others)
_.difference = function(array) {
// 将 others 数组展开一层
// rest[] 保存展开后的元素组成的数组
// strict 参数为 true
// 不可以这样用 _.difference([1, 2, 3, 4, 5], [5, 2], 10);
// 10 就会取不到
var rest = flatten(arguments, true, true, 1);
// 遍历 array,过滤
return _.filter(array, function(value){
// 如果 value 存在在 rest 中,则过滤掉
return !_.contains(rest, value);
});
};
不熟悉 flatten 的可以看看 前文,当 shallow 和 strict 均为 true 时,展开一层,并且过滤非数组元素,即可以起到将多个数组合并的作用。之后利用 ._filter 进行过滤即可。
而 _.without 方法则建立在 _.difference 基础上。
_.without = function(array) {
// slice.call(arguments, 1)
// 将 arguments 转为数组(同时去掉第一个元素)
// 之后便可以调用 _.difference 方法
return _.difference(array, slice.call(arguments, 1));
};
总结
数组的扩展方法就解读到这里了,相关源码可以参考 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 支持我~
【跟着子迟品 underscore】Array Functions 相关源码拾遗 & 小结的更多相关文章
- 【跟着子迟品 underscore】Object Functions 相关源码拾遗 & 小结
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
- 【跟着子迟品 underscore】如何优雅地写一个『在数组中寻找指定元素』的方法
Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...
- 【跟着子迟品 underscore】JavaScript 中如何判断两个元素是否 "相同"
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
- 【跟着子迟品 underscore】JavaScript 数组展开以及重要的内部方法 flatten
Why underscore (觉得这一段眼熟的童鞋可以直接跳到正文了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...
- 【跟着子迟品 underscore】for ... in 存在的浏览器兼容问题你造吗
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
- 【跟着子迟品 underscore】常用类型判断以及一些有用的工具方法
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
- 【跟着子迟品underscore】从用 `void 0` 代替 `undefined` 说起
Why underscore 最近开始看 underscore源码,并将 underscore源码解读 放在了我的 2016计划 中. 阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多 ...
- Volley 图片加载相关源码解析
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/47721631: 本文出自:[张鸿洋的博客] 一 概述 最近在完善图片加载方面的 ...
- MFC界面相关源码
这是这4篇MFC界面的相关源码.建议学习Visual C++的看看这2本微软官方出的教材. [MFC Windows程序设计(第2版,修订版)](美)Jeff Prosise著 [Windows程序设 ...
随机推荐
- C语言中把数字转换为字符串 【转】
在将各种类型的数据构造成字符串时,sprintf 的强大功能很少会让你失望.由于sprintf 跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出 ...
- autocomplete="off" 不起作用
首先来了解一下 表单自动填充的原理,当我们登录的时候,如果选择的记住登录密码,那么后续界面中如果有 <input type="text" name="field1& ...
- javascript移动设备Web开发中对touch事件的封装实例
在触屏设备上,一些比较基础的手势都需要通过对 touch 事件进行二次封装才能实现.zepto 是移动端上使用率比较高的一个类库,但是其 touch 模块模拟出来的一些事件存在一些兼容性问题,如 ta ...
- AO安装需要Microsoft Visual Studio 2013?
从接触ArcGIS9.2到 10.4,在不断升级的 过程中,既给我们带来了很多惊喜,也带来一些麻烦,因为ArcGIS版本不兼容.出于体验,安装了ArcGIS Desktop10.4,AO也得升到10. ...
- 玩转大麦盒子airplay
长城宽待送了大麦盒子,一直没怎么用,既然是安卓的系统,那估计可以安装很多的软件吧,今天演练了一下. 大麦盒子 规格和介绍 http://baike.so.com/doc/7487612.html 有G ...
- 用Kotlin开发Android应用(III):扩展函数和默认值
这是关于Kotlin的第三篇. 原文标题:Kotlin for Android (III): Extension functions and default values 原文链接:http://an ...
- [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
关联 关联是指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分. 关联特性只有在Mac OS X V10.6以及以后的版本上才是可用的. 在类的定义之外为类增加额外的存储空间 ...
- iOS crash 追终 ,iOS 如何定位crash 位置
https://developer.apple.com/library/ios/technotes/tn2151/_index.html 错误分析是基于设备中的crash log 与 编译文件时生成的 ...
- Android 轻松实现仿淘宝地区选择
介绍 最近用淘宝客户端的时候,编辑地址的时候有个地区选择的功能.看上面的效果觉得挺酷,滚动的时候,是最后一个从下面飞上来挨着前一个.就自己鼓捣一个出来玩玩. 说了效果可能不太直观,下面上两张图看看效果 ...
- Linux系统检查查看桌面环境
Linux的桌面系统系统多达十几种,像gnome.kde.mate.cinnamon.lxde.xfce.jwm等.比较常用的一般是gnome.kde.xfce等.那么如何判断Linux系统安装了哪种 ...