IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> underscore.js源码整体框架解析 -> 正文阅读

[JavaScript知识库]underscore.js源码整体框架解析

源码框架

读一些库的源码时最头疼的其实不是里面各个函数的功能,而是整体结构框架,通常库的源码都很长,跟框架相关的代码并不是在一起放着的,导致你想明白起来就很困难。
我看过通过画图的方式去讲解框架的,但看完以后还是一头雾水,甚至越看越懵逼,各种箭头绕来绕去对理解框架是然并卵的。
身为一个程序员,代码其实是最直接的。
并且框架这种底层的东西,原理一定是很简单的。
即便是复杂如整个互联网的架构,每一层网络模型的原理也都是很简单的。
所以想理解框架,最好的方式就是把跟框架相关的代码提取并精炼出来,其他乱七八糟的东西一定是在这之上展开的。
以下就是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

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:02:05  更:2022-04-04 12:04:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:36:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码