underscore.js源码研究(8)
概述
很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以就了结研究underscore源码这一心愿吧。
underscore.js源码研究(1)
underscore.js源码研究(2)
underscore.js源码研究(3)
underscore.js源码研究(4)
underscore.js源码研究(5)
underscore.js源码研究(6)
underscore.js源码研究(7)
underscore.js源码研究(8)
参考资料:underscore.js官方注释,undersercore 源码分析,undersercore 源码分析 segmentfault
链式调用
对于一个对象的方法,我们可以在方法里面return this来使它支持链式调用。如果不修改原方法的源码,我们可以通过下面的函数使它支持链式调用。
//其中obj是一个对象,functions是对象的方法名数组
function chained(obj, functions) {
//由于functions是一个数组,所以可以使用foreach
functions.forEach((funcName) => {
const func = obj[funcName];
//修改原方法
obj[funcName] = function() {
func.apply(this, arguments);
return this;
}
})
}
示例如下:
let speaker = {
haha() {
console.log('haha');
},
yaya() {
console.log('yaya');
},
lala() {
console.log('lala');
}
}
chained(speaker, ['haha', 'lala', 'yaya']);
speaker.haha().yaya().haha().lala().yaya();
输出如下:
haha
yaya
haha
lala
yaya
underscore.js里面的链式调用
underscore.js里面的链式调用与上面的稍微有些不同。
它的机制是这样的:
- 把underscore.js的方法全部挂载到_下面。
- 利用_.function方法遍历所有挂载在_下面的方法,然后挂载到_.prototype下面,这样生成的underscore对象就可以直接调用这些方法了。
- 在把方法挂载到_.prototype下面的时候,会利用类似上面的函数对方法进行改写(增加return this)。
- 在改写的时候建立一个标识_chain,来标识这个方法能不能链式调用。
下面来具体看看是怎么运作的:
首先,利用下面的函数,可以得到一个数组,这个数组里面全是挂载到_下面的方法名字。
_function = _.methods = function(obj) {
var names = [];
for( var key in obj) {
if(_.isFunction(obj[key])) names.push(key);
}
return names.sort();
};
然后我们对每一个方法名字,把它挂载到_.prototype下面:
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return chainResult(this, func.apply(_, args));
};
});
};
_.mixin(_);
从上面可以看到,在挂载的时候返回一个chainResult方法处理过的东西。而args就等于原对象+参数1+参数2+...组成的数组,所以func.apply(_, args)
就是_[func](原对象,参数1,参数2,...)
处理后的结果。
再来看看chainResult是怎么样的:
var chainResult = function(instance, obj){
return instance._chain ? _(obj).chain() : obj;
};
它判断如果原对象能够链式调用,那么处理后的结果obj也能够链式调用。怎么让结果也能链式调用呢?答案是使用_.chain方法:
_chain = function(obj) {
var instance = _(obj);
instance._chain = true;
return instance;
}
这个方法和我们最开始的chained方法差不多,但是它会把原对象转化为underscore对象,并且这个对象的_chain属性为真,即它能够被链式调用。
所以如果我们要在underscore.js中实现链式调用的话,直接用chain方法即可,实例如下:
_([1,2]).push(3).push(5) //输出4,并不是我们想要的
_([1,2]).chain().push(3).push(5).value() //输出[1, 2, 3, 5],正是我们想要的
可以看到,我们上面用到了value()函数,它能够中断链式调用,并不返回指针而是返回值,代码如下:
_.prototype.value = function() {
return this._wrapped;
}
等等,_wrapped又是什么?它是生成underscore对象前的原对象,看下面的代码:
var _ = function(obj) {
if(obj instanceof _) return obj;
if(!(this instanceof _)) return new _(obj);
this._wrapped = obj;
}
也就是说,在使用_生成underscore对象的时候,把原对象储存在_wrapped属性里面了,所以_wrapped就是原对象。
underscore.js源码研究(8)的更多相关文章
- underscore.js源码研究(7)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码研究(6)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码研究(5)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码研究(4)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码研究(3)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码研究(2)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码研究(1)
概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...
- underscore.js源码解析(五)—— 完结篇
最近公司各种上线,所以回家略感疲惫就懒得写了,这次我准备把剩下的所有方法全部分析完,可能篇幅过长...那么废话不多说让我们进入正题. 没看过前几篇的可以猛戳这里: underscore.js源码解析( ...
- underscore.js 源码
underscore.js 源码 underscore]JavaScript 中如何判断两个元素是否 "相同" Why underscore 最近开始看 underscore.js ...
随机推荐
- 20155312 2016-2017-2 《Java程序设计》第九周学习总结
20155312 2016-2017-2 <Java程序设计>第九周学习总结 课堂内容总结 两个类有公用的东西放在父类里. 面向对象的三要素 封装 继承 多态:用父类声明引用,子类生成对象 ...
- MySQL LOCK TABLES 与UNLOCK TABLES
http://blog.csdn.net/zyz511919766/article/details/16342003 1语法 LOCK TABLES tbl_name[[AS] alias] lock ...
- GUI的优化操作/添加背景图片等
一.背景图片的添加这是JAVA中添加背景图片的方式,基本思路先建立一个Label标签,然后建立一个层次的布局,将label标签添加到最下面去. ImageIcon image=new ImageIco ...
- mysql之存储引擎和文件配置
(查看系统服务,在运行里输入services.msc) 补充:将mysql做成系统服务:mysqld --install 取消:mysqld --romove 在服务中可以直接鼠标操作mysql服务的 ...
- Java数组的初始化
1.动态初始化 数据类型 [] 变量名 = new 数据类型 [数组大小]; //数组的动态初始化 int [] arr = new int [3]; 2.静态初始化 数据类型 [] 变量名 = {元 ...
- kvm虚拟化平台搭建
一.虚拟化 虚拟化是指计算机元件在虚拟的基础上而不是真实的基础上运行.虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程.CPU的虚拟化技术可以单CPU模 拟多CPU并行,允许一个平台同时运行多个操 ...
- excel中vba将excel中数字和图表输出到word中
参考:https://wenku.baidu.com/view/6c60420ecc175527072208af.html 比如将选区变为图片保存到桌面: Sub 将选区转为图片存到桌面() Dim ...
- 详细介绍jQuery.outerWidth() 函数具体用法
outerWidth()函数用于设置或返回当前匹配元素的外宽度.外宽度默认包括元素的内边距(padding).边框(border),但不包括外边距(margin)部分的宽度.你也可以指定参数为true ...
- 查看Redis集群所有节点内存工具
指定集群中任意一个节点,查看集群中所有节点当前已用物理内存.配置的最大物理内存和系统物理内存. 源码(可从https://github.com/eyjian/redis-tools下载): #! ...
- Ng第七课:正则化与过拟合问题 Regularization/The Problem of Overfitting
7.1 过拟合的问题 7.2 代价函数 7.3 正则化线性回归 7.4 正则化的逻辑回归模型 7.1 过拟合的问题 如果我们有非常多的特征,我们通过学习得到的假设预测可能能够非常好地适应训练 ...