每次看源码都要感叹一句,哎,我头疼的英语呀!!!
(function() {
// this === window
var root = this;
// 全局变量 previousUnderscore保存_的值,主要是为了防止_被占用,可以使用_.noConflict()恢复
var previousUnderscore = root._;
// 用变量保存数组,对象,函数,的原型
// 这个是为了以后压缩出更小的体积,Array.prototype 是不能压缩的,否则js解析器就不认识了,ArrayProto却可以直接压缩成变量o
var ArrayProto = Array.prototype,
ObjProto = Object.prototype,
FuncProto = Function.prototype;
// 保存一些原型方法,压缩了,还有后面使用也方便,很多地方都判断如果具有原型方法,就使用原型方法,否则使用补丁方法
var
push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
var
nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// 这是一个原型引用的裸对象,后面会用到
var Ctor = function(){};
// 就是添加_wrapped = obj,类似于迭代。
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
// 这里是兼容node的模块,以及打包时的变量引用
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}
// 版本
_.VERSION = '1.8.2';
// Internal:内部
// efficient:有效率的
// current:现在的
// engines:发动机
// (for current engines):对于目前的引擎
// repeatedly:反复地
// 返回一个有效的(当前引擎)版本的内部函数在回调中传递的,可复用于其他的'_'.
// 这个函数在内部用的特别多,好多地方都是用这里做迭代的
var optimizeCb = function(func, context, argCount) {
// 如果 context = undefined 则返回函数本身
if (context === void 0) return func;
// 如果argCount不存在或者等于3
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
// 一个主要的内部函数生成回调函数可以应用对集合中的每一个元素,
//返回所需的结果-或者身份,任意一个回调,一个属性或属性访问器。
var cb = function(value, context, argCount) {
// 返回 '_' 本身
if (value == null) return _.identity;
// 如果是函数,则调用optimizeCb
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
// 返回对象本身,matcher用来鉴别是否是对象
if (_.isObject(value)) return _.matcher(value);
// 添加值到property
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
// 创建一个内部函数分配器功能。
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
// 如果参数不存在,并且找不到obj,则返回'_'
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// 创建一个从另一个继承的新对象的内部函数。
// result 继承了Ctor的原型 ,Ctor只是用来过度的,用后就被抛弃了
// 基本就是一个过渡函数
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
// collection : 收集
// 一个内部函数,确保数组的length是有效的。
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
// 确定是一个列表,并且有length属性
var isArrayLike = function(collection) {
var length = collection != null && collection.length;
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// 定义插件方法,
var result = function(instance, obj) {
return instance._chain ? _(obj).chain() : obj;
};
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
};
// 将_上的方法,全部添加到原型对象上
_.mixin(_);
// 兼容使用 AMD 的模块化方式
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
}.call(this));
网友评论