上次写过一篇的文章,个人认为,想要了解一个库或框架,首先从他的核心思想入手,理解其思想,那么剩余的就仅仅是方法的堆砌。近年比较火的一个jsMVC框架他的核心强依赖库为。
抽空提取了一下他的骨骼,其实主要就是他的链式操作的实现,别个剩下的就是具体函数的实现了,当然对于Underscore函数式也是它的最大亮点,可以好好看下函数的实现。
<! DOCTYPE html > < html > < head > < title > Underscore骨骼 < / title> < / head> < body > < script type = " text/javascript " > // Underscore骨骼 ( function () { var root = this ; var breaker = {}; var ArrayProto = Array.prototype, ObjProto = Object.prototype; var nativeForEach = ArrayProto.forEach, nativeMap = ArrayProto.map, nativeFilter = ArrayProto.filter, nativeKeys = Object.keys; var slice = ArrayProto.slice, unshift = ArrayProto.unshift, hasOwnProperty = ObjProto.hasOwnProperty; // 构造函数 var _ = function (obj) { return new wrapper(obj); }; // 向全局暴露接口 root._ = _; // 类型检测 _.isNumber = function (obj) { return !! (obj === 0 || (obj && obj.toExponential && obj.toFixed)); }; _.isFunction = function (obj) { return !! (obj && obj.constructor && obj.call && obj.apply); }; // 遍历扩展 var each = _.each = _.forEach = function (obj, iterator, context) { if (obj === null ) return ; if (nativeForEach && obj.forEach === nativeForEach) { obj.forEach(iterator, context); } else if (_.isNumber(obj.length)) { for ( var i = 0 , l = obj.length; i < l; i ++ ) { if (iterator.call(context, obj[i], i, obj) === breaker) return ; } } else { for ( var key in obj) { if (hasOwnProperty.call(obj, key)) { if (iterator.call(context, obj[key], key, obj) === breaker) return ; } } } }; // 返回对象上面的函数名 _.functions = _.methods = function (obj) { return _.filter(_.keys(obj), function (key) { return _.isFunction(obj[key])}).sort(); }; // 过滤数组 _.filter = _.select = function (obj, iterator, context) { var results = []; if (obj == null ) return results; if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); each(obj, function (value, index, list) { if (iterator.call(context, value, index, list)) results[results.length] = value; }); return results; }; // 获取key值 _.keys = nativeKeys || function (obj) { if (obj !== Object(obj)) throw new TypeError( ' Invalid object ' ); var keys = []; for ( var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; return keys; }; // 用于实验的map方法 _.map = function (obj, iterator, context) { var results = []; if (obj == null ) return results; if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); each(obj, function (value, index, list) { results[results.length] = iterator.call(context, value, index, list); }); return results; }; // 链式操作主要部分 var wrapper = function (obj) { this ._wrapped = obj; }; _.prototype = wrapper.prototype; // 扩展自定义方法到Wrap包装器上 _.mixin = function (obj) { each(_.functions(obj), function (name) { addToWrapper(name, _[name] = obj[name]); }); }; // 是否对结果进行链式包装返回 var result = function (obj, chain) { return chain ? _(obj).chain() : obj; }; // 将方法扩展到包装器的原型上 var addToWrapper = function (name, func) { wrapper.prototype[name] = function () { var args = slice.call(arguments); unshift.call(args, this ._wrapped); return result(func.apply(_, args), this ._chain); }; }; // 将所有Underscore上的方法添加到Wrap包装器上 _.mixin(_); // 扩展Array上的方法到wrap包装器上-包装原数组 each([ ' pop ' , ' push ' , ' reverse ' , ' shift ' , ' sort ' , ' splice ' , ' unshift ' ], function (name) { var method = ArrayProto[name]; wrapper.prototype[name] = function () { method.apply( this ._wrapped, arguments); return result( this ._wrapped, this ._chain); }; }); // 扩展Array上的方法到wrap包装器上-包装返回值 each([ ' concat ' , ' join ' , ' slice ' ], function (name) { var method = ArrayProto[name]; wrapper.prototype[name] = function () { return result(method.apply( this ._wrapped, arguments), this ._chain); }; }); // 添加链式方法的实现 wrapper.prototype.chain = function () { this ._chain = true ; return this ; }; // 提取链式包装的内容 wrapper.prototype.value = function () { return this ._wrapped; };})(); // 结果测试 步骤:将数组[1,2,3]进行链式包装,然后将其用val * 2来map,紧接着用filter进行val < 5过滤, // 然后pop,concat最后获取其值value var re = _([ 1 , 2 , 3 ]).chain().map( function (val) { return val * 2 ;}).filter( function (val) { return val < 5 ;}).pop().concat([ ' 5 ' ]).value();alert(re); < / script> < / body>
< /html>