什么是underscore
underscore作为开发中比较常用的一个javascript工具库,提供了一套丰富的函数式编程功能,该库并没有拓展原有的javascript原生对象,而是在自定义的_对象上,提供了100多个方法函数。它是帮助我们进行js增强的一个库。 和它类似的有lodash
编程思想之流式编程
学习underscore源码,精髓在于学习他的函数式编程的架构思想。 我们学习了解一下stream流式编程 流是一系列数据项,一次只生成一项。程序可以从输入流中一个一个读取数据项,再写入输出流。 我们可以理解为每个函数都是管道的一部分,这个函数的结果可以作为另一个函数的参数。最终通过拼接完成我们的需求。
underscore的封装思想,可以通过两种方式调用
一个库,我们既可以用函数的方式去调用,也可以用对象的方式去调用。怎么实现呢?
ccc.filter(xxx) 或者通过 ccc(xxx).fliter 去调用
下面我们看一下,一个库内部怎么封装的原理,可以通过对象或者函数的形式去使用这个库,对于以后我们自己封装一些库是很有帮助的。
我们知道,函数本身也是对象的一种,所以我们可以把函数本身自己的功能逻辑放到自己的原型链上去,这样就实现了两种的调用方式。
(function(root){
let _ = function(){
// 如果_ 中的this不是指向 _,说明它不是对象,而是作为构造函数,我们直接返回它的实例。
// 当链式调用的时候,已经是实例了,就不会再去new
if(!(this instanceof _)){
return new _()
}
}
// 函数上的方法,new的实例是没有的。
_.show = function(){
console.log('show1')
}
_.prototype.show = function(){
console.log('show2')
}
// 挂载到window上
root._ = _
})(this)
但是上面的方法太死板了,等于是构造函数上面弄一套,原型对象上弄一套。 定义一个混入函数,_.mixin,遍历去添加方法到原型上即可。
(function(root){
let _ = function(data){
// 如果_ 中的this不是指向 _,说明它不是对象,而是作为构造函数,我们直接返回它的实例。
// 当链式调用的时候,已经是实例了,就不会再去new
if(!(this instanceof _)){
return new _(data)
}
this.data = data
}
// 函数上的方法,原型上的实例是没有的。
_.show = function(){
console.log('show1')
}
// 定义函数,返回函数的所有属性,给mixin使用
_.keyArr = function(target){
let arr = []
for(let key in target){
arr.push(key)
}
return arr
}
// 功能拆分,通过回调函数的形式处理数组的每一个元素
_.handleArr = function(arr,callback){
for(let i =0;i<arr.length;i++){
callback(arr[i])
}
}
// 定义一个mixin函数,混入函数上的方法到原型对象上给实例用
_.mixin = function(target){
_.handleArr(_.keyArr(target),(item)=>{
let fn = target[item]
_.prototype[item] = function(){
fn(this.data)
}
})
}
_.mixin(_)
// 挂载到window上
root._ = _
})(this)
上面的代码mixin就是一个工具函数,会自动把构造函数上的所有方法都挂载到它的原型对象上。 这样我们以后扩展的时候,只需要给构造函数加属性即可。 这个思想就是用函数去管理函数,也是高阶函数的一个应用。 当然,真框架封装的时候会考虑更多的扩展性,包裹校验,参数的个数不同的扩展,我们可以通过简化来理解它的思想。