underscore源码学习笔记

一、集合

  1. 首先是几个迭代的方法。
_.each = _.forEach = function(obj, iteratee, context) {iteratee = optimizeCb(iteratee, context);var i, length;if (isArrayLike(obj)) {for (i = 0, length = obj.length; i < length; i++) {iteratee(obj[i], i, obj);}} else {var keys = _.keys(obj);for (i = 0, length = keys.length; i < length; i++) {iteratee(obj[keys[i]], keys[i], obj);}}// 链式调用return obj;
};

ES为数组同样添加了原生的forEach()方法。不同的是这里的each(forEach)方法可以对所有集合使用,函数接受三个参数(集合、迭代函数、执行环境)。

optimizeCb函数根据迭代函数参数个数的不同为不同的迭代方法绑定了相应的执行环境,forEach迭代函数同样接受三个参数(值,索引,集合)。
接下来就是for循环调用迭代函数了。

_.map中一种更优雅的判断isArrayLike的实现方式:(只用一个for循环)

var keys = !isArrayLike(obj) && _.keys(obj),length = (keys || obj).length,results = Array(length);for (var index = 0; index < length; index++) {var currentKey = keys ? keys[index] : index;results[index] = iteratee(obj[currentKey], currentKey, obj);}
return results;// 合理使用&&、||、?:可以大大减少代码量

还有两个特别的地方:

  • 将集合分成了类数组集合和对象集合。使用了isArrayLike函数:
// js的最大精确整数
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection) {var length = collection != null && collection.length;return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
}; // 如果集合有Length属性且为数字并且大于0小于最大的精确整数,则判定是类数组
  • 使用了_.keys函数,Object同样有原生的keys函数,用于返回一个集合obj可被枚举的属性数组。实现比较简单,for in加上hasOwnProperty()方法。

_.map,_.reduce方法原理类似.
_.find函数和Array.some()类似,不同的是返回的是第一个使迭代结果为真的那个元素,而不是Array.some()那样返回布尔值。

_.find = _.detect = function(obj, predicate, context) {var key;if (isArrayLike(obj)) {key = _.findIndex(obj, predicate, context);} else {key = _.findKey(obj, predicate, context);}if (key !== void 0 && key !== -1) return obj[key];
};
function createIndexFinder(dir) {return function(array, predicate, context) {predicate = cb(predicate, context);var length = array != null && array.length;// 如果dir为1,index为0,index+=1,index正序循环// 如果dir 为-1,index为length-1,index += -1反序循环// 判断循环条件则用了index >= 0 && index < length方法兼顾两种循环方式var index = dir > 0 ? 0 : length - 1;for (; index >= 0 && index < length; index += dir) {if (predicate(array[index], index, array)) return index;}return -1;};
}
_.findIndex = createIndexFinder(1);
_.findLastIndex = createIndexFinder(-1);

值得借鉴的地方是这里的一个for循环能够根据传入的参数不同配置不同的循环顺序。

  1. 集合中的其他方法基本都是基于迭代方法来实现的。
_.max = function(obj, iteratee, context) {var result = -Infinity, lastComputed = -Infinity,value, computed;if (iteratee == null && obj != null) {obj = isArrayLike(obj) ? obj : _.values(obj);for (var i = 0, length = obj.length; i < length; i++) {value = obj[i];if (value > result) {result = value;}}} else {iteratee = cb(iteratee, context);_.each(obj, function(value, index, list) {computed = iteratee(value, index, list);if (computed > lastComputed || computed === -Infinity && result === -Infinity) {result = value;lastComputed = computed;}});}return result;
};

max方法用于寻找集合中的最大值,通过循环list中的所有项,然后比较当前项和结果项,如果当前项大于结果,则将其赋给结果项,最后返回结果项。

  1. 集合转换为数组
_.toArray = function(obj) {if (!obj) return [];// 如果是数组,采用了Array.prototype.slice.call(this,obj)这种方法if (_.isArray(obj)) return slice.call(obj);// 类数组对象,这里没有采用Slice方法,而是利用.map对集合进行迭代,从而返回一个数组。 _.identity该方法传入的值和返回的值相等。(主要用于迭代)xif (isArrayLike(obj)) return _.map(obj, _.identity);// 普通对象,则返回由属性值组成的数组。return _.values(obj);
};

转载于:https://www.cnblogs.com/black-star/p/5087515.html

underscore源码学习笔记(一)相关推荐

  1. Java多线程之JUC包:Semaphore源码学习笔记

    若有不正之处请多多谅解,并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/go2sea/p/5625536.html Semaphore是JUC ...

  2. RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的?

    RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 文章目录 RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 前言 项目 ...

  3. Vuex 4源码学习笔记 - 通过Vuex源码学习E2E测试(十一)

    在上一篇笔记中:Vuex 4源码学习笔记 - 做好changelog更新日志很重要(十) 我们学到了通过conventional-changelog来生成项目的Changelog更新日志,通过更新日志 ...

  4. Vuex 4源码学习笔记 - Vuex是怎么与Vue结合?(三)

    在上一篇笔记中:Vuex源码学习笔记 - Vuex开发运行流程(二) 我们通过运行npm run dev命令来启动webpack,来开发Vuex,并在Vuex的createStore函数中添加了第一个 ...

  5. jquery源码学习笔记三:jQuery工厂剖析

    jquery源码学习笔记二:jQuery工厂 jquery源码学习笔记一:总体结构 上两篇说过,query的核心是一个jQuery工厂.其代码如下 function( window, noGlobal ...

  6. 雷神FFMpeg源码学习笔记

    雷神FFMpeg源码学习笔记 文章目录 雷神FFMpeg源码学习笔记 读取编码并依据编码初始化内容结构 每一帧的视频解码处理 读取编码并依据编码初始化内容结构 在开始编解码视频的时候首先第一步需要注册 ...

  7. Apache log4j-1.2.17源码学习笔记

    (1)Apache log4j-1.2.17源码学习笔记 http://blog.csdn.net/zilong_zilong/article/details/78715500 (2)Apache l ...

  8. PHP Yac cache 源码学习笔记

    YAC 源码学习笔记 本文地址 http://blog.csdn.net/fanhengguang_php/article/details/54863955 config.m4 检测系统共享内存支持情 ...

  9. Vuex 4源码学习笔记 - 通过dispatch一步步来掌握Vuex整个数据流(五)

    在上一篇笔记中:Vuex 4源码学习笔记 - Store 构造函数都干了什么(四) 我们通过查看Store 构造函数的源代码可以看到主要做了三件事情: 初始化一些内部变量以外 执行installMod ...

  10. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

最新文章

  1. [bbk4966]第70集 第8章 -性能维护 01
  2. android8.1内核编译,Android8.1.0安卓源码编译
  3. Sicily/1282. Computer Game
  4. android 日期选择器
  5. php 伪静态是什么意思,路由与伪静态
  6. 机动车驾驶人科目三考试项目及合格标准
  7. 中小型互联网企业迁移上云,保证云端资源安全迁移
  8. vue router-link子级返回父级页面
  9. oracle 切割字符串加引号_Oracle 在字符串中输入单引号或特殊字符
  10. 软工实践项目课程的自我目标
  11. PyTorch系列入门到精通——张量操作线性回归
  12. mysql 乱码处理
  13. matlab连接散射点,使用小波散射做信号分类
  14. 产品经理三大文档--BRD、MRD、PRD解读
  15. 如何下载免费版的PDF编辑器
  16. 【整理】CRISPR-Cas9用于病毒性传染病防控的最新进展
  17. bzoj4570: [Scoi2016]妖怪【凸包+对勾函数最小值】
  18. 实验一:Cifar10图像分类竞赛 学习记录
  19. HTML之网页布局与设计技巧
  20. vue 项目 想修改代码严格模式 lintOnSave

热门文章

  1. Mysql 中将blob类型转换成varchar类型
  2. SQL SERVER 2008的转置函数PIVOT
  3. 批量 // 注释替换为 /*的注释
  4. TCP/IP协议栈的封装
  5. RemoveDirectory 功能:删除文件夹
  6. Spark-Unit1-spark概述与安装部署
  7. 洛谷P2939 [USACO09FEB]改造路Revamping Trails(最短路)
  8. Proj.4 API 中文参考
  9. iOS 循环引用 委托 (实例说明)
  10. 温暖的《北国之恋》_ing