读一些库的源码时最头疼的其实不是里面各个函数的功能,而是整体结构框架,通常库的源码都很长,跟框架相关的代码并不是在一起放着的,导致你想明白起来就很困难。
我看过通过画图的方式去讲解框架的,但看完以后还是一头雾水,甚至越看越懵逼,各种箭头绕来绕去对理解框架是然并卵的。
身为一个程序员,代码其实是最直接的。
并且框架这种底层的东西,原理一定是很简单的。
即便是复杂如整个互联网的架构,每一层网络模型的原理也都是很简单的。
所以想理解框架,最好的方式就是把跟框架相关的代码提取并精炼出来,其他乱七八糟的东西一定是在这之上展开的。
以下就是underscore.js提炼出来的框架代码。
把这块代码放到一个js文件中当作新的库文件,就足以模拟整个underscore的框架了,完全可以独立运行的。
所有解析都在注释中。
注释中有源码所对应的行数。
版本为1.11.0 esm版。
部分代码我进行了改写,以便于大家的理解。
// underscore版本 1.11.0 esm版
// 303行
// _其实是个构造函数
function _(obj) {
// 这么写 就可以不用new去实例化了,而是像普通函数一样实例化,比较容易迷惑人!
if (!(this instanceof _)) return new _(obj)
// 缓存上一次链式调用的结果值
this._wrapped = obj
}
// 312行
// 单个增加原型方法,_构造函数生成的实例就可以调用了
_.prototype.value = function() {
return this._wrapped;
};
// 各种功能函数。。。
function fun1() {
console.log('调用函数fun1')
return 'res'
}
// 878行
// 包装普通对象为可供链式调用的对象
function chain(obj) {
var instance = _(obj)
instance._chain = true
return instance
}
// 1728行
// 链式调用如果没有结束,则将上次结果进行再包装,供下次链式调用使用
function chainResult(instance, obj) {
return instance._chain ? _(obj).chain() : obj
}
// 1733行
// _上混入功能函数,文档上的方法基本都是_构造函数的静态方法
// _上的原型方法也会在这里挂载,为了链式调用时可以使用,因为chain方法的返回值就是_的实例
function mixin(obj) {
let funArr = Object.keys(obj)
// 在_构造函数上增加各种静态方法
funArr.forEach(name=> {
_[name] = obj[name]
})
// 在_构造函数上增加各种原型方法,链式调用时使用
funArr.forEach(name=> {
const func = obj[name]
_.prototype[name] = function() {
// !!!这里就是为啥链式调用时不需要再传文档里的第一个参数
// 因为this._wrapped缓存了上一次处理的结果值,在这里合并成新的参数传递给下一个链式调用函数
var args = [this._wrapped, ...arguments]
return chainResult(this, func.apply(_, args))
}
})
// 将处理过的_构造函数返回,供export使用
return _
}
// 1772行
// 要导出的所有功能函数
var allExports = {
fun1: fun1,
chain: chain
}
// 1923行
// 将要导出的功能函数混入到_ ,并起一个新名字,供导出用
var _$1 = mixin(allExports)
// 1929行
// 导出新名字
export default _$1
其中最难理解的部分就是链式调用相关的代码,如果抛开这块,就是贼简单的一个框架。
链式调用相关请仔细看注释。
以上代码保存为module.js文件,在另一个js文件中引入,就可以使用了。
import _ from './module.js'
let arg1 = 'arg1'
_.fun1() // res
// 链式调用
let res = _.chain(arg1).fun1().fun1().value()
console.log(res) // res
还看不懂的话只能去补补基础知识了,只能帮你到这啦。
许多库其实用的都是类似这种的结构,对外导出的变量就是一个构造函数,挂载各类静态方法以及原型方法来扩充,因为对外暴露的变量通常就只有一个。
欢迎来我的b站空间逛逛
https://space.bilibili.com/395672451