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