首先,有个单例对象,它上面挂了很多静态工具方法。其中有一个是each,用来遍历数组或对象。
复制代码 代码如下:
var nativeForEach = [].forEach
var nativeMap = [].map
var util = {
each: function (obj, iterator, context) {
if (obj == null) return
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context)
} else if ( obj.length === +obj.length ) {
for (var i = 0; i < obj.length; i++) {
if (iterator.call(obj[i] || context, obj[i], i, obj) === true) return
}
} else {
for (var k in obj) {
if (iterator.call(obj[k] || context, obj[k], k, obj) === true) return
}
}
},
map: function(obj, iterator, context) {
var results = []
if (obj == null) return results
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context)
this.each(obj, function(val, i, coll) {
results[i] = iterator.call(context, val, i, coll)
})
return results
}
}
还有诸如every、some等对集合(Array,Hash)操作的工具函数。使用时采用util.xx方式。
如果定义了一个集合类,这个类内部有集合数据。
复制代码 代码如下:
function Collection(data) {
this.data = data || []
// some other property
// this.xxx = yyy
}
Collection.prototype = {
// some method
}
可以很方便的把util上的方法拷贝到集合类上,如
复制代码 代码如下:
function copyMethod(clazz, obj) {
for (var method in obj) {
clazz.prototype[method] = function() {
var args = [].slice.call(arguments)
var target = this.data
args.unshift(target)
obj[method].apply(obj, args)
}
}
}
copyMethod(Collection, util)
这样拷贝后,Collection的实例就有了util上的方法,util操作的集合对象(第一个参数)就是Collection的this.data。如下直接可以遍历this.data了。
复制代码 代码如下:
var coll = new Collection([10, 20, 30])
// 遍历
coll.each(function(k) {
console.log(k)
})
// 操作
var arr = coll.map(function(k) {
return k - 5
})
console.log(arr) // 5, 15, 25
这种模式在很多开源库中使用,比如jQuery,它的 $.each/$.map 很方便的拷贝到了 $().each/$().map。
又如Backbone,它的 _.each/_.map/_.every/_.chain (还有很多)都拷贝到了 Collection的原型上。
复制代码 代码如下:
// Underscore methods that we want to implement on the Collection.
// 90% of the core usefulness of Backbone Collections is actually implemented
// right here:
var methods = ["forEach", "each", "map", "collect", "reduce", "foldl",
"inject", "reduceRight", "foldr", "find", "detect", "filter", "select",
"reject", "every", "all", "some", "any", "include", "contains", "invoke",
"max", "min", "toArray", "size", "first", "head", "take", "initial", "rest",
"tail", "drop", "last", "without", "difference", "indexOf", "shuffle",
"lastIndexOf", "isEmpty", "chain"];
// Mix in each Underscore method as a proxy to `Collection#models`.
_.each(methods, function(method) {
Collection.prototype[method] = function() {
var args = slice.call(arguments);
args.unshift(this.models);
return _[method].apply(_, args);
};
});
又有,把 _.keys / _.values / _.pairs / _.invert / _.pick 等对对象操作的实用方法拷贝了 Backbone.Model上 (1.0新增)
复制代码 代码如下:
var modelMethods = ["keys", "values", "pairs", "invert", "pick", "omit"];
// Mix in each Underscore method as a proxy to `Model#attributes`.
_.each(modelMethods, function(method) {
Model.prototype[method] = function() {
var args = slice.call(arguments);
args.unshift(this.attributes);
return _[method].apply(_, args);
};
});