在学习underscore.js源码之前,我们先来了解下js模块管理发展的几个历程。
任何编程语言都有一套模块化的代码结构组织思想,同样js也存在,由于js早期特殊的创作历程,导致它缺乏一个统一的语言规范,之后加入了ECMA以及node.js的出现形成的CommonJS规范,js语言逐渐走上正规的发展道路,我们知道underscore.js诞生于js被标准化之前,在这之前,js的工具库都采用“立即调用函数表达式”也被成为IIFE( Immediately Invoked Function Expression)的形式来组织代码结构,回到历史,我们通过对underscore.js骨架代码分析,来学习这种代码组织形式.// 组织形式1,通过return对象提供外部访问入口var _ = (function(){ var modules = {}; // 封装对外访问的方法 modules.helloworld = function() { console.log("hello world!"); }; return modules;})()_.helloworld() //hello world!// 将内部方法绑定到全局对象上(function(){ var root = this; var _ = {}; // 挂载到全局对象上 root._ = _; // 封装对外访问的方法 _.helloworld = function() { console.log("hello world!"); };})()_.helloworld() //hello world!
比较以上两段代码都实现了模块封装,第一种是通过返回挂载对象,外部接受该对象进行调用,第二种是将对外的函数入口挂载到全局对象上,外部进行调用
再来看下underscore.js的框架结构
(function(){ // ...}.call(this))
这里使用了call,来看下func.call(this)这句代码是什么意思?
var func = function() { console.log("我是一个打印函数");}func.call(this) // 我是一个打印函数func() // 我是一个打印函数
这种写法同我们前边的挂载全局写法一样,js语法很灵活,写法也很灵活。
到此,我们实现了一个underscore.js代码的基本骨架,然后就是一个个方法挂载到"_"这个对象上,外部进行调用。