lodash 之 Chain

Chain

可以说是 lodash 中最为重要的部件,想要用lodash进行复杂的多步操作都离不开chain的帮助。

首先说说Chain的调用方式有两种:一种是显式调用(Explicit Chaining),一种是隐式调用(Implicit Chaining)。

//下面的例子采用了ECMAScript2015的语法:
//显式调用例子如下:
let numbers = [1, 2, 3, 4, 5];
let sumOfEvenSquares = _.chain(numbers) //注意numbers放置的位置
    .filter(n => n % 2 === 0)
    .map(n => n * n)
    .sum()
    .value();    
//sumOfEvenSquares: 20
//特别要注意结尾的那个.value()
//隐式调用例子如下:
let sumOfEvenSquares = _(numbers) //注意numbers的位置,不需要显式的使用chain关键字
    .filter(n => n % 2 === 0)
    .map(n => n * n)
    .sum()
let isEven = n => n % 2 === 0;
let square = n => n * n;
let sumOfEvenSquares = _(numbers).filter(isEven).map(square).sum();

从上面例子可以看出,隐式调用比显式调用更加简洁方便。
为什么要多出来一个 .value(),而不是直接出结果呢?那是因为可能要等待延时(Deferred execution)数据的到来,再执行取值。这就是我们常说的Lazy evaluation (延迟计算/惰性求值)

//如下面的例子:首先生成链式表达式
var wallet = _(assets).filter(ownedBy('me'))
                      .pluck('value')
                      .reduce(sum);

$json.get("/new/assets").success(function(data) {
    assets.push.apply(assets, data);     // 然后更新数据
    wallet.value();                      // 最后求值
});

隐式
_(value)建立了一个隐式链对象,可以把那些能操作并返回 arrays(数组)、collections(集合)、functions(函数)的”.Methods”(lodash的函数)串起来。 那些能返回“唯一值(single value)”或者可能返回原生数据类型(primitive value)会自动结束链式反应。

显式
而显式链则用_.chain. 的方式实现延迟计算,即:求值操作等到 _value()被调用时再执行。
延迟计算允许一些方法支持shortcut fusion 。由于执行被延后了,因此lodash可以进行shortcut fusion这样的优化,通过合并链式iteratee大大降低迭代的次数。

另外,lodash wrappers 还支持Array和String的一些方法:

The wrapper Array methods are(支持wrapper的Array方法有):
concat, join, pop, push, reverse,shift, slice, sort, splice, unshift

The wrapper String methods are(支持wrapper的String方法有):
replace,split

The wrapper methods that support shortcut fusion are(支持shortcut fusion的方法有):
compact, drop, dropRight, dropRightWhile, dropWhile, filter, first, initial, last,map, pluck, reject, rest, reverse, slice, take, takeRight, takeRightWhile, takeWhile, toArray, where

he chainable wrapper methods are(可以链式反应的wrapper方法有):
after, ary, assign, at, before, bind, bindAll, bindKey, callback, chain, chunk, commit, compact,concat, constant, countBy, create, curry, debounce, defaults,defaultsDeep, defer, delay, difference, drop, dropRight, dropRightWhile, dropWhile, fill, filter, flatten, flattenDeep, flow, flowRight, forEach, forEachRight, forIn, forInRight, forOwn, forOwnRight, functions, groupBy, indexBy, initial, intersection,
invert, invoke, keys, keysIn, map, mapKeys, mapValues, matches,
matchesProperty, memoize, merge, method, methodOf, mixin, modArgs, negate, omit, once, pairs, partial, partialRight, partition, pick,
plant, pluck, property, propertyOf, pull, pullAt, push, range, rearg,
reject, remove, rest, restParam, reverse, set, shuffle, slice, sort,
sortBy, sortByAll, sortByOrder, splice, spread, take, takeRight,
takeRightWhile, takeWhile, tap, throttle, thru, times, toArray,
toPlainObject, transform, union, uniq, unshift, unzip, unzipWith,
values, valuesIn, where, without, wrap, xor, zip, zipObject, zipWith

缺省(不能直接加在"链条中间" 立即执行计算)

The wrapper methods that are not chainable by default are(缺省情况下不能加在”链条”中间的wrapper方法有):
add, attempt, camelCase, capitalize, ceil, clone, cloneDeep, deburr, endsWith, escape,escapeRegExp, every, find, findIndex, findKey, findLast,findLastIndex, findLastKey, findWhere, first, floor, get, gt, gte, has, identity, includes, indexOf, inRange, isArguments, isArray,isBoolean, isDate, isElement, isEmpty, isEqual, isError, isFinite, isFunction, isMatch, isNative, isNaN, isNull, isNumber, isObject, isPlainObject, isRegExp, isString, isUndefined, isTypedArray, join, kebabCase, last, lastIndexOf, lt, lte, max, min, noConflict, noop, now, pad, padLeft, padRight, parseInt, pop, random, reduce, reduceRight, repeat, result, round, runInContext, shift, size, snakeCase, some, sortedIndex, sortedLastIndex, startCase, startsWith, sum, template, trim, trimLeft, trimRight, trunc, unescape, uniqueId, value, words

//举个例子:
var wrapped = _([1, 2, 3]);

// 隐式链中,reduce是属于不能直接加在"链条中间"(not chainable)的,所以能立即执行计算
wrapped.reduce(function(total, n) {
  return total + n;
});
// → 6

// 而map是chainable的
var squares = wrapped.map(function(n) {
  return n * n;
});

//所以不调用value()时返回的并不是一个Array而是一个wrapper
_.isArray(squares);
// → false

//调用了value后返回的就是一个wrapper了
_.isArray(squares.value());
// → true

_.tap(value, interceptor, [thisArg])

拦截器,拿tap来干嘛?你可以在链条当中插它一下,可以对数据进行处理,可以返回值也可以不返回值,也可以仅仅是打印一下中间的过程,拿tap来debug 链式反应的过程是不错的选择。

_([1, 4, 3, 5])
 .tap(function(array) {
   array.pop();              //对array进行操作
   console.log(array);       //打印
   return array.reverse();   //返回值,也可以不返回值
 })
 .value();                   //取值
// → [3,4,1]

_.thru(value, interceptor, [thisArg])

和 tap非常相似,但是必须有返回值,否则会报错!

_('  abc  ')
 .chain()
 .trim()
 .thru(function(value) {
   return '处理后:[' + value + ']';   //必须有返回值
 })
 .value();
// → 处理后:[abc]

_.prototype.chain()

允许wrapper对象使用显式链。这样就允许隐式链可以切换为显式链。

var users = [
  { 'user': '阿帕奇', 'age': 36 },
  { 'user': '弗雷德',   'age': 40 }
];

//第一个例子没用显式链,注意first()在缺省情况下是只能被加在反应链尾部的
//参看前面的 ***not chainable***
_(users).first();
// → { 'user': '阿帕奇', 'age': 36 }

// 第二个例子启用了显式链,在启用了chain后,first就可以加到链条中间了
_(users).chain()
  .first()
  .pick('user')
  .value();
// → { 'user': '阿帕奇' }

_.prototype.commit()

执行链条并返回wrapped instance;
要注意与.prototype.value()的区别,commit()与value()都会触发链式反应,但是返回的值不同

var array = [1, 2];

var wrapped = _(array).push(3);

console.log(array);
// → [1, 2] 这个时候 array的值还没有发生变化

wrapped = wrapped.commit();

console.log(wrapped);
//{ __wrapped__: [ 1, 2, 3 ], __actions__: [], __chain__: false }

console.log(array);
// → [1, 2, 3] 在commit之后 array的值发生变化了

wrapped.last();
// → 3

_.prototype.value()

执行链条,并且返回unwrapped后的值,注意与上边.commit()的比较

_([1, 2, 3]).value();
// → [1, 2, 3]

_.prototype.concat([values])

新建一个数组,将原始数组与新加入的值合并起来。

var array = [1];
var wrapped = _(array).concat(2, [3], [[4]]);

console.log(wrapped.value());
// → [1, 2, 3, [4]]

console.log(array);
// → [1]  注意:原数组并未发生改变

_.prototype.plant()

克隆一个已有的操作链

var array = [1, 2];
var wrapped = _(array).map(function(value) {
  return Math.pow(value, 2);
});

var other = [3, 4];
var otherWrapped = wrapped.plant(other);

otherWrapped.value();
// → [9, 16]

wrapped.value();
// → [1, 4]

_.prototype.reverse()

反转数组元素的次序:注意改方法会改变被操作的数组。

var array = [1, 2, 3];

_(array).reverse().value()
// → [3, 2, 1]

console.log(array);
// → [3, 2, 1]

_.prototype.toString()

将unwrapped 的值转为字符串。

_([1, 2, 3]).toString();
// → '1,2,3'

你可能感兴趣的:(vant,react)