chain
_.chain(lyrics)
.map(function(line) { return line.words.split(' '); })
.flatten()
.reduce(function(counts, word) {
counts[word] = (counts[word] || 0) + 1;
return counts;
}, {})
.value();
Underscore
支持鏈?zhǔn)秸{(diào)用募胃;不過要求函數(shù)鏈的開頭要用chain
函數(shù)生成封裝對象。
看看chain
到底做了啥灌砖。
_.chain = function (obj) {
var instance = _(obj);
instance._chain = true;
return instance;
};
chain
生成了返回了一個(gè)underscore
實(shí)例
var _ = function (obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
我們看到underscore
實(shí)例就是一個(gè)掛載了_wrapper
的對象刁品。
再接著,因?yàn)?code>_是個(gè)構(gòu)造函數(shù)回论,所有方法都是掛載在構(gòu)造函數(shù)上的散罕。
Underscore
提供了mixin
方法為Underscore
對象進(jìn)行擴(kuò)展,我們看看傀蓉。
_.mixin = function (obj) {
_.each(_.functions(obj), function (name) {
// 對傳入的obj欧漱,遍歷它所有的方法,先掛載在構(gòu)造函數(shù)上
var func = _[name] = obj[name];
// 并且所有的方法都會在原型上重寫葬燎;
_.prototype[name] = function () {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
};
_.mixin(_);
Underscore
通過mixin
將原來掛載在構(gòu)造函數(shù)上所有的方法误甚,全部在_
的原型上重寫缚甩,這次重寫,直接指定了underscore
所有方法的第一個(gè)參數(shù)為this._wrapped
窑邦,也就是構(gòu)造函數(shù)攜帶的參數(shù)擅威。
然后看看最后為了鏈?zhǔn)秸{(diào)用返回的result
函數(shù)。明顯支持這種“不帶”第一個(gè)參數(shù)的寫法是只能寫在underscore
實(shí)例上的冈钦。所以在原型上重寫的方法郊丛,最后返回的仍然是underscore
實(shí)例。
var result = function (instance, obj) {
return instance._chain ? _(obj).chain() : obj;
};
也就是說瞧筛,underscore
的鏈?zhǔn)秸{(diào)用一直返回的是一個(gè)_
的實(shí)例厉熟,_
的構(gòu)造方法不僅掛載了全部underscore
的方法,并且在原型上重寫了這些方法较幌,使得_
的實(shí)例可以不用傳遞第一個(gè)參數(shù)而進(jìn)行鏈?zhǔn)秸{(diào)用庆猫。