Why underscore

最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中。

阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多。为什么是 underscore?最主要的原因是 underscore 简短精悍(约 1.5k 行),封装了 100 多个有用的方法,耦合度低,非常适合逐个方法阅读,适合楼主这样的 JavaScript 初学者。从中,你不仅可以学到用 void 0 代替 undefined 避免 undefined 被重写等一些小技巧 ,也可以学到变量类型判断、函数节流&函数去抖等常用的方法,还可以学到很多浏览器兼容的 hack,更可以学到作者的整体设计思路以及 API 设计的原理(向后兼容)。

之后楼主会写一系列的文章跟大家分享在源码阅读中学习到的知识。

欢迎围观~ (如果有兴趣,欢迎 star & watch~)您的关注是楼主继续写作的动力

Main

趁着今天是工作日的最后一天,把源码解读部分 Object Functions 更新完毕。

如果你有心,可能就会发现楼主之前的解读系列文章说的都是 Object 上的扩展方法,也就是源码中 Object Functions 部分。underscore 为 5 种类型添加了扩展方法,分别是 Object -> Array -> Collection -> Function -> Utility,这也正是楼主的源码解读顺序(并不是源码顺序)。其中,Object 上的扩展方法多达 38 个,方法多并不代表代码多,比如类型检测,两行代码就可以搞定好几个方法,而上一篇中说的 _.isEqual 方法,却要百来行去实现。今天是 Object Functions 部分的最后一篇,我们来看看楼主认为的几个没被解读过的但是却有意思的方法的源码。(其实很多方法使用简单,实现也非常简单,有兴趣的同学可以自己扒下源码)

_.pick

首先来看看 _.pick 方法,该方法传入一个对象,然后删选对象的键值对,返回一个对象副本。

直接来看例子:

_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
=> {name: 'moe', age: 50}

_.pick({name: 'moe', age: 50, userid: 'moe1'}, ['name', 'age']);
=> {name: 'moe', age: 50}

_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
  return _.isNumber(value);
});
=> {age: 50}

一目了然,第一个参数 obj 是对象,第二个参数可以是一系列的 key 值,也可以是数组(数组中含 key),也可以是迭代函数,我们根据 key 值,或者迭代函数来过滤 obj 中的键值对,返回新的对象副本。

如果让我来设计,估计会根据参数来判断类型,然后写几个 if-else,每个 if-else 分支里的内容毫无关联。但是 underscore 的写法简直美妙,将几种情况转为了一种。

// 如果第二个参数是函数
if (_.isFunction(oiteratee)) {
  keys = _.allKeys(obj);
  iteratee = optimizeCb(oiteratee, context);
}

首先 if-else 是不可避免的,如果传入的第二个参数是 function,那么就是传入迭代函数了,根据 context(this)返回新的迭代函数(optimizeCb 我以后会讲,就是规定了迭代函数中的 this 指向,不是很重要,这里可以选择性忽略)。

如果第二个参数不是函数,则后面的 keys 可能是数组,也可能是连续的几个并列的参数。这里我们要用到 underscore 中另一个重要的内部方法,flatten,它的作用是将嵌套的数组展开,这个方法我以后会分析,这里知道它的作用就可以了。

else {
  // 如果第二个参数不是函数
  // 则后面的 keys 可能是数组
  // 也可能是连续的几个并列的参数
  keys = flatten(arguments, false, false, 1);

  // 也转为 predicate 函数判断形式
  // 将指定 key 转化为 predicate 函数
  iteratee = function(value, key, obj) { return key in obj; };
  obj = Object(obj);
}

也转为和传入迭代函数一样的形式,就可以用一个方法判断了,而且 keys 变量在两种情况下的意义是不同的,真的非常巧妙。这点令我思考良多,很多时候的代码冗余,其实大概是自己代码能力太差了吧,打死我也想不到这样做。

_.create

_.create 方法非常简单,根据你给的原型(prototype),以及一些 own properties,构造新的对象返回。

举个简单的例子:

var Person = function() {};

Person.prototype = {
  show: function() {
    alert(this.name);
  }
};

var me = _.create(Person.prototype, {name: 'hanzichi'});

console.log(me);

// Object {name: "hanzichi"}
//   name: "hanzichi"
//   __proto__: Object
//     show: function()

其实 me 变量就是一个拥有 name 作为 own properties,且用 Person 函数构造的对象。

如果浏览器支持 ES5,我们可以用 Object.create()

var Person = function() {};

Person.prototype = {
  show: function() {
    alert(this.name);
  }
};

var me = Object.create(Person.prototype);

_.extendOwn(me, {name: 'hanzichi'});

console.log(me);

如果不支持 ES5,我们可以新定义一个构造函数,将该构造函数的 prototype 赋值为已知的 prototype 变量,然后用 new 运算符来获取实例:

var Person = function() {};

Person.prototype = {
  show: function() {
    alert(this.name);
  }
};

var _Person = function() {};

_Person.prototype = Person.prototype;

var me = new _Person();

_.extendOwn(me, {name: 'hanzichi'});

console.log(me);

undercore 的实现思路也大抵如此。

_.tap

本来打算把 _.tap 讲掉,突然觉得跟链式调用一起讲比较好,挖个坑。

小结

关于 Objects Function 部分的源码剖析就到这了,具体这部分代码可以参考 https://github.com/hanzichi/underscore-analysis/blob/master/underscore-1.8.3.js/src/underscore-1.8.3.js#L901-L1269。虽然说看完了这部分代码,但是要真正理解消化还是需要时间的,我只能说自己理解了 90% 左右,欢迎探讨交流。

接下去应该会着手看 Array 扩展方法相关代码,继续为大家整理有意思的东西,各种奇淫怪巧,敬请期待。

【跟着子迟品 underscore】Object Functions 相关源码拾遗 & 小结的更多相关文章

  1. 【跟着子迟品 underscore】Array Functions 相关源码拾遗 & 小结

    Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...

  2. 【跟着子迟品 underscore】如何优雅地写一个『在数组中寻找指定元素』的方法

    Why underscore (觉得这部分眼熟的可以直接跳到下一段了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

  3. 【跟着子迟品 underscore】JavaScript 中如何判断两个元素是否 "相同"

    Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...

  4. 【跟着子迟品 underscore】JavaScript 数组展开以及重要的内部方法 flatten

    Why underscore (觉得这一段眼熟的童鞋可以直接跳到正文了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

  5. 【跟着子迟品 underscore】for ... in 存在的浏览器兼容问题你造吗

    Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...

  6. 【跟着子迟品 underscore】常用类型判断以及一些有用的工具方法

    Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...

  7. 【跟着子迟品underscore】从用 `void 0` 代替 `undefined` 说起

    Why underscore 最近开始看 underscore源码,并将 underscore源码解读 放在了我的 2016计划 中. 阅读一些著名框架类库的源码,就好像和一个个大师对话,你会学到很多 ...

  8. Volley 图片加载相关源码解析

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/47721631: 本文出自:[张鸿洋的博客] 一 概述 最近在完善图片加载方面的 ...

  9. MFC界面相关源码

    这是这4篇MFC界面的相关源码.建议学习Visual C++的看看这2本微软官方出的教材. [MFC Windows程序设计(第2版,修订版)](美)Jeff Prosise著 [Windows程序设 ...

随机推荐

  1. iOS如何用代码控制以不同屏幕方向打开新页面?

    转载:http://blogread.cn/it/article/7765?f=wb#original 代码示例:https://github.com/johnlui/Swift-On-iOS/tre ...

  2. CSS3动画属性Transform解读

    无论你是前端还是设计师,相信你在网页二维空间上的操作早已经得心应手,JS处理时间线的动画也早已经 烂熟于胸.从今天开始,我跟大家分享一些“新”的东西,网页的第三个维度,以及纯CSS实现的动画.限于篇幅 ...

  3. HTML5学习笔记一 简单学习HTML5

    什么是HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言: HyperText Markup Language HTML 不是一种编程语言,而是一种标记语言 标记语言是一 ...

  4. AFNetworking的理解

    AFNetworking的理解 使用方法 1. 新建的工程中导入AFNetworking3.0中的(AFNetworking 和UIKit+AFNetworking两个文件夹) 2. 在用到AFNet ...

  5. WebView的使用

    1.首先修改activity.xml中的代码: 2.然后MainActivity中的代码: 3.最后设置权限: <uses-permission android:name="andro ...

  6. ios textfield / textview长按复制粘贴中文显示

    当我们在写应用时要复制粘贴文本框内容时,默认显示的文字为英文字体,可按如下步骤设置,显示中文:

  7. iOS面试题总结 (三)

    22 键值编码KVC KVC全称key valued coding 键值编码 提到KVC,就不能不提反射机制,反射机制就是在运行状态中,对于任意一个类,都能够调用他的所有属性和方法,对于任意一个对象, ...

  8. Android性能优化之内存优化练习

    练习题目地址:https://github.com/lzyzsd/MemoryBugs 分析及优化过程如下: 问题1 静态变量引用activity 使用神器LeakCanary检查内存泄露问题 从图中 ...

  9. Linux如何搜索查找文件里面内容

    在Linux系统当中,如何搜.索查找文件里面的内容呢? 这个应该是系统维护.管理当中遇到最常见的需求.那么下面介绍,总结一下如何搜索.查找文件当中的内容. 搜索.查找文件当中的内容,一般最常用的是gr ...

  10. .NET并行编程实践(一:.NET并行计算基本介绍、并行循环使用模式)

    阅读目录: 1.开篇介绍 2.NET并行计算基本介绍 3.并行循环使用模式 3.1并行For循环 3.2并行ForEach循环 3.3并行LINQ(PLINQ) 1]开篇介绍 最近这几天在捣鼓并行计算 ...