// Underscore.js 1.3.3
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function() {
// 创建一个全局对象, 在浏览器中表示为window对象, 在Node.js中表示global对象
var root = this;
// 保存"_"(下划线变量)被覆盖之前的值
// 如果出现命名冲突或考虑到规范, 可通过_.noConflict()方法恢复"_"被Underscore占用之前的值, 并返回Underscore对象以便重新命名
var previousUnderscore = root._;
// 创建一个空的对象常量, 便于内部共享使用
var breaker = {};
// 将内置对象的原型链缓存在局部变量, 方便快速调用
var ArrayProto = Array.prototype, //
ObjProto = Object.prototype, //
FuncProto = Function.prototype;
// 将内置对象原型中的常用方法缓存在局部变量, 方便快速调用
var slice = ArrayProto.slice, //
unshift = ArrayProto.unshift, //
toString = ObjProto.toString, //
hasOwnProperty = ObjProto.hasOwnProperty;
// 这里定义了一些JavaScript 1.6提供的新方法
// 如果宿主环境中支持这些方法则优先调用, 如果宿主环境中没有提供, 则会由Underscore实现
var nativeForEach = ArrayProto.forEach, //
nativeMap = ArrayProto.map, //
nativeReduce = ArrayProto.reduce, //
nativeReduceRight = ArrayProto.reduceRight, //
nativeFilter = ArrayProto.filter, //
nativeEvery = ArrayProto.every, //
nativeSome = ArrayProto.some, //
nativeIndexOf = ArrayProto.indexOf, //
nativeLastIndexOf = ArrayProto.lastIndexOf, //
nativeIsArray = Array.isArray, //
nativeKeys = Object.keys, //
nativeBind = FuncProto.bind;
// 创建对象式的调用方式, 将返回一个Underscore包装器, 包装器对象的原型中包含Underscore所有方法(类似与将DOM对象包装为一个jQuery对象)
var _ = function(obj) {
// 所有Underscore对象在内部均通过wrapper对象进行构造
return new wrapper(obj);
};
// 针对不同的宿主环境, 将Undersocre的命名变量存放到不同的对象中
if( typeof exports !== 'undefined') {// Node.js环境
if( typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {// 浏览器环境中Underscore的命名变量被挂在window对象中
root['_'] = _;
}
// 版本声明
_.VERSION = '1.3.3';
// 集合相关的方法(数据和对象的通用处理方法)
// --------------------
// 迭代处理器, 对集合中每一个元素执行处理器方法
var each = _.each = _.forEach = function(obj, iterator, context) {
// 不处理空值
if(obj == null)
return;
if(nativeForEach && obj.forEach === nativeForEach) {
// 如果宿主环境支持, 则优先调用JavaScript 1.6提供的forEach方法
obj.forEach(iterator, context);
} else if(obj.length === +obj.length) {
// 对<数组>中每一个元素执行处理器方法
for(var i = 0, l = obj.length; i < l; i++) {
if( i in obj && iterator.call(context, obj[i], i, obj) === breaker)
return;
}
} else {
// 对<对象>中每一个元素执行处理器方法
for(var key in obj) {
if(_.has(obj, key)) {
if(iterator.call(context, obj[key], key, obj) === breaker)
return;
}
}
}
};
// 迭代处理器, 与each方法的差异在于map会存储每次迭代的返回值, 并作为一个新的数组返回
_.map = _.collect = function(obj, iterator, context) {
// 用于存放返回值的数组
var results = [];
if(obj == null)
return results;
// 优先调用宿主环境提供的map方法
if(nativeMap && obj.map === nativeMap)
return obj.map(iterator, context);
// 迭代处理集合中的元素
each(obj, function(value, index, list) {
// 将每次迭代处理的返回值存储到results数组
results[results.length] = iterator.call(context, value, index, list);
});
// 返回处理结果
if(obj.length === +obj.length)
results.length = obj.length;
return results;
};
// 将集合中每个元素放入迭代处理器, 并将本次迭代的返回值作为"memo"传递到下一次迭代, 一般用于累计结果或连接数据
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
// 通过参数数量检查是否存在初始值
var initial = arguments.length > 2;
if(obj == null)
obj = [];
// 优先调用宿主环境提供的reduce方法
if(nativeReduce && obj.reduce === nativeReduce && false) {
if(context)
iterator = _.bind(iterator, context);
return initial "" + i);
// 返回的结果是一个二维数组
return results;
};
// 搜索一个元素在数组中首次出现的位置, 如果元素不存在则返回 -1
// 搜索时使用 === 对元素进行匹配
_.indexOf = function(array, item, isSorted) {
if(array == null)
return -1;
var i, l;
if(isSorted) {
i = _.sortedIndex(array, item);
return array[i] === item " '
_.escape = function(string) {
return ('' + string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/');
};
// 指定一个对象的属性, 返回该属性对应的值, 如果该属性对应的是一个函数, 则会执行该函数并返回结果
_.result = function(object, property) {
if(object == null)
return null;
// 获取对象的值
var value = object[property];
// 如果值是一个函数, 则执行并返回, 否则将直接返回
return _.isFunction(value) "'" : "'",
'r' : '\r',
'n' : '\n',
't' : '\t',
'u2028' : '\u2028',
'u2029' : '\u2029'
};
// 遍历所有特殊字符字符串, 并以特殊字符作为key记录字符串形式
for(var p in escapes)
escapes[escapes[p]] = p;
// 定义模板中需要替换的特殊符号, 包含反斜杠, 单引号, 回车符, 换行符, 制表符, 行分隔符, 段落分隔符
// 在将字符串中的特殊符号转换为字符串形式时使用
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
// 在将字符串形式的特殊符号进行反转(替换)时使用
var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
// 反转字符串中的特殊符号
// 在模板中涉及到需要执行的JavaScript源码, 需要进行特殊符号反转, 否则如果以HTML实体或字符串形式出现, 会抛出语法错误
var unescape = function(code) {
return code.replace(unescaper, function(match, escape) {
return escapes[escape];
});
};
// Underscore模板解析方法, 用于将数据填充到一个模板字符串中
// 模板解析流程:
// 1. 将模板中的特殊符号转换为字符串
// 2. 解析escape形式标签, 将内容解析为HTML实体
// 3. 解析interpolate形式标签, 输出变量
// 4. 解析evaluate形式标签, 创建可执行的JavaScript代码
// 5. 生成一个处理函数, 该函数在得到数据后可直接填充到模板并返回填充后的字符串
// 6. 根据参数返回填充后的字符串或处理函数的句柄
// -------------------
// 在模板体内, 可通过argments获取2个参数, 分别为填充数据(名称为obj)和Underscore对象(名称为_)
_.template = function(text, data, settings) {
// 模板配置, 如果没有指定配置项, 则使用templateSettings中指定的配置项
settings = _.defaults(settings || {}, _.templateSettings);
// 开始将模板解析为可执行源码
var source = "__p+='" + text.replace(escaper, function(match) {
// 将特殊符号转移为字符串形式
return '\\' + escapes[match];
}).replace(settings.escape || noMatch, function(match, code) {
// 解析escape形式标签 <%- %>, 将变量中包含的HTML通过_.escape函数转换为HTML实体
return "'+\n_.escape(" + unescape(code) + ")+\n'";
}).replace(settings.interpolate || noMatch, function(match, code) {
// 解析interpolate形式标签 <%= %>, 将模板内容作为一个变量与其它字符串连接起来, 则会作为一个变量输出
return "'+\n(" + unescape(code) + ")+\n'";
}).replace(settings.evaluate || noMatch, function(match, code) {
// 解析evaluate形式标签 <% %>, evaluate标签中存储了需要执行的JavaScript代码, 这里结束当前的字符串拼接, 并在新的一行作为JavaScript语法执行, 并将后面的内容再次作为字符串的开始, 因此evaluate标签内的JavaScript代码就能被正常执行
return "';\n" + unescape(code) + "\n;__p+='";
}) + "';\n";
if(!settings.variable)
source = 'with(obj||{}){\n' + source + '}\n';
source = "var __p='';" + "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" + source + "return __p;\n";
// 创建一个函数, 将源码作为函数执行体, 将obj和Underscore作为参数传递给该函数
var render = new Function(settings.variable || 'obj', '_', source);
// 如果指定了模板的填充数据, 则替换模板内容, 并返回替换后的结果
if(data)
return render(data, _);
// 如果没有指定填充数据, 则返回一个函数, 该函数用于将接收到的数据替换到模板
// 如果在程序中会多次填充相同模板, 那么在第一次调用时建议不指定填充数据, 在获得处理函数的引用后, 再直接调用会提高运行效率
var template = function(data) {
return render.call(this, data, _);
};
// 将创建的源码字符串添加到函数对象中, 一般用于调试和测试
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
// 没有指定填充数据的情况下, 返回处理函数句柄
return template;
};
// 支持Underscore对象的方法链操作, 可参考 wrapper.prototype.chain
_.chain = function(obj) {
return _(obj).chain();
};
// Underscore对象封装相关方法
// ---------------
// 创建一个包装器, 将一些原始数据进行包装
// 所有的undersocre对象, 内部均通过wrapper函数进行构造和封装
// Underscore与wrapper的内部关系:
// -内部定义变量_, 将Underscore相关的方法添加到_, 这样就可以支持函数式的调用, 如_.bind()
// -内部定义wrapper类, 将_的原型对象指向wrapper类的原型
// -将Underscore相关的方法添加到wrapper原型, 创建的_对象就具备了Underscore的方法
// -将Array.prototype相关方法添加到wrapper原型, 创建的_对象就具备了Array.prototype中的方法
// -new _()时实际创建并返回了一个wrapper()对象, 并将原始数组存储到_wrapped变量, 并将原始值作为第一个参数调用对应方法
var wrapper = function(obj) {
// 原始数据存放在包装对象的_wrapped属性中
this._wrapped = obj;
};
// 将Underscore的原型对象指向wrapper的原型, 因此通过像wrapper原型中添加方法, Underscore对象也会具备同样的方法
_.prototype = wrapper.prototype;
// 返回一个对象, 如果当前Underscore调用了chain()方法(即_chain属性为true), 则返回一个被包装的Underscore对象, 否则返回对象本身
// result函数用于在构造方法链时返回Underscore的包装对象
var result = function(obj, chain) {
return chain ? _(obj).chain() : obj;
};
// 将一个自定义方法添加到Underscore对象中(实际是添加到wrapper的原型中, 而Underscore对象的原型指向了wrapper的原型)
var addToWrapper = function(name, func) {
// 向wrapper原型中添加一个name函数, 该函数调用func函数, 并支持了方法链的处理
wrapper.prototype[name] = function() {
// 获取func函数的参数, 并将当前的原始数据添加到第一个参数
var args = slice.call(arguments);
unshift.call(args, this._wrapped);
// 执行函数并返回结果, 并通过result函数对方法链进行封装, 如果当前调用了chain()方法, 则返回封装后的Underscore对象, 否则返回对象本身
return result(func.apply(_, args), this._chain);
};
};
// 将内部定义的_(下划线, 即Underscore方法集合对象)中的方法复制到wrapper的原型链中(即Underscore的原型链中)
// 这是为了在构造对象式调用的Underscore对象时, 这些对象也会具有内部定义的Underscore方法
_.mixin(_);
// 将Array.prototype中的相关方法添加到Underscore对象中, 因此在封装后的Underscore对象中也可以直接调用Array.prototype中的方法
// 如: _([]).push()
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
// 获取Array.prototype中对应方法的引用
var method = ArrayProto[name];
// 将该方法添加到Underscore对象中(实际是添加到wrapper的原型对象, 因此在创建Underscore对象时同时具备了该方法)
wrapper.prototype[name] = function() {
// _wrapped变量中存储Underscore对象的原始值
var wrapped = this._wrapped;
// 调用Array对应的方法并返回结果
method.apply(wrapped, arguments);
var length = wrapped.length;
if((name == 'shift' || name == 'splice') && length === 0)
delete wrapped[0];
// 即使是对于Array中的方法, Underscore同样支持方法链操作
return result(wrapped, this._chain);
};
});
// 作用同于上一段代码, 将数组中的一些方法添加到Underscore对象, 并支持了方法链操作
// 区别在于上一段代码所添加的函数, 均返回Array对象本身(也可能是封装后的Array), concat, join, slice方法将返回一个新的Array对象(也可能是封装后的Array)
each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
wrapper.prototype[name] = function() {
return result(method.apply(this._wrapped, arguments), this._chain);
};
});
// 对Underscore对象进行链式操作的声明方法
wrapper.prototype.chain = function() {
// this._chain用来标示当前对象是否使用链式操作
// 对于支持方法链操作的数据, 一般在具体方法中会返回一个Underscore对象, 并将原始值存放在_wrapped属性中, 也可以通过value()方法获取原始值
this._chain = true;
return this;
};
// 返回被封装的Underscore对象的原始值(存放在_wrapped属性中)
wrapper.prototype.value = function() {
return this._wrapped;
};
}).call(this);
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
白云城资源网 Copyright www.dyhadc.com
暂无“Underscore.js 1.3.3 中文注释翻译说明”评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
2025年11月01日
2025年11月01日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]