underscore源码分析系列-1-整体结构

前言

一直希望有一个机会可以阅读某库的源码,并写一些自己的想法和思考,最终将目标定在underscore,一个纯粹的js工具库,没有dom、bom的参与。

underscore.js

整体框架

首先我们来看一下,underscore工具库的整体框架

verison 1.8.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(function(){
//拿到一个全局对象,browser中是window对象,server中是exports
var root = this;
// 缓存一些原生js的原型以及es5的方法
// ...
//underscore工具库的构造函数
var _ = function(obj){
if(obj instanceof _) return obj;
if(!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
//将构造函数暴露给全局
if(typeof exports !== 'undefined'){
if(typeof module !== 'undefined' && module.exports){
exports = module.exports = _;
}
exports._=_;
} else {
root._ = _;
}
// 版本
_.VERSION = '1.8.3';
/*underscore中一些内部变量和函数*/
//...
/*提供给外部调用的静态api*/
_.each = function(){
//TODO
};
_.first = function(){
//TODO
};
_.bind = function(){
//TODO
};
_.keys = function(){
//TODO
};
_.noConfict = function(){
//TODO
};
_.chain = function(){
//TODO
};
//...
//一些原型上面的方法
_.prototype.value = function(){
//TODO
};
//...
//支持amd
if (typeof define === 'function' && define.amd) { define('underscore', [], function() {
return _;
});
}
}).call(this);

大体框架如上所述

接下来我们看一下underscore库刚开始设置哪些后面要用到的常用的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var root = this;
// 保存引进underscore库之前可能存在于全局对象下面的_属性值,主要给noConflict静态函数做去冲突用
var previousUnderscore = root._;
// 保存一些长江的构造函数的原型,数组,对象,函数等
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
// 保存一些数组的常见方法
var
push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
// 保存es5的一些方法
var
nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeBind = FuncProto.bind,
nativeCreate = Object.create;

underscore构造函数

最后我们来看一下,构造函数本身。

1
2
3
4
5
var _ = function(obj) {
if (obj instanceof _) return obj; // 如果传进来的obj是_的实例,那么直接将obj返回
if (!(this instanceof _)) return new _(obj); // 如果不是_的实例,那么内部直接new 一个 _的实例,然后返回
this._wrapped = obj; // 给_的实例挂一个属性_wrapped,并赋值为obj
};

underscore构造函数内部这样处理,可以保证不管外部是否适用new的形式调用,都会拿到一个underscore实例

结尾

underscore.js第一篇就先到这里,了解了其整体的结构,接下来我们开始分析一些比较常用的函数。