摘要:学习冴羽的博客研究 underscore 中 cb 和 optimizeCb 函数
_.map
_.map 函数中有使用 cb 函数:
1 | // 简化过,这里仅假设 obj 是数组 |
_.map 的三个参数: obj 是待处理数据; iteratee 是处理函数; context 是指定的执行上下文,即 this 的值
cb
cb 函数源码:
1 | var cb = function (value, context, argCount) { |
cb 函数对传入的 value 值类型进行判断,然后根据不同的类型,返回不同的函数。涉及到 8 个函数,其中 _.iteratee 、 _.identity 、optimizeCb 、 _.matcher 、 _.property 这五个函数还没有接触过
_.iteratee
_.iteratee 的源码:
1 | _.iteratee = builtinIteratee = function (value, context) { |
因为源码中_.iteratee = builtinIteratee
,所以通常情况下_.iteratee !== builtinIteratee
为 false。但是当我们在外部修改 _.iteratee 函数后,则返回 true,执行_.iteratee(value, context)
,也就是使用自定义的 _.iteratee 函数来处理 value 和 context
因为 underscore 中的多个函数都使用了 cb 函数,而 cb 函数又使用了 _.iteratee 函数,所以要修改 _.iteratee 函数的话,一定要谨慎操作
_.identity
_.identity 的源码:
1 | _.identity = function(value) { |
_.identity 函数就是将传入的第一个参数原样返回,当 value 值为 null 或 undefined 时,返回 _.identity
optimizeCb
optimizeCb 的源码:
1 | var optimizeCb = function (func, context, argCount) { |
传入的三个参数:func 是处理函数; context 是指定的执行上下文 this ; argCount 是返回函数参数的个数
void的返回值都是undefined,用void 0是为了防止undefined被重写而出现判断不准确的情况
ES5之后的标准中,规定了全局变量下的undefined值为只读,不可改写的,但是局部变量中依然可以对之进行改写。
中间使用 switch 对 argCount 进行判断而不是直接返回下面的匿名函数,可以避免使用 arguments 以提高一点性能
_.matcher
_.matcher 的源码:
1 | var nativeIsArray = Array.isArray; |
_.matcher 就是用来处理当 map 的第二个参数是对象的情况
调用效果如下:
1 | _.map([{name:'Kevin'}, {name: 'Daisy', age: 18}], {name: 'Daisy'}); // [false, true] |
_.property
_.property 的源码:
1 | _.property = function (path) { |
_.property 用来处理当 value 是基本类型的值的情况,会返回元素对应的属性值
调用效果如下:
1 | _.map([{ name: 'Kevin' }, { name: 'Daisy' }], 'name'); // ['Kevin', 'daisy'] |