上次写过一篇QWrap骨骼的文章,个人认为,想要了解一个库或框架,首先从他的核心思想入手,理解其思想,那么剩余的就仅仅是方法的堆砌。近年比较火的一个jsMVC框架backbone他的核心强依赖库为underscore。
抽空提取了一下他的骨骼,其实主要就是他的链式操作的实现,别个剩下的就是具体函数的实现了,当然对于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 >
< 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>