underscore.js 652 --- 748行

// Generator function to create the findIndex and findLastIndex functions.
  var createPredicateIndexFinder = function(dir) {
    return function(array, predicate, context) {
      predicate = cb(predicate, context);
      var length = getLength(array);
      var index = dir > 0 ? 0 : length - 1;
      for (; index >= 0 && index < length; index += dir) {
        if (predicate(array[index], index, array)) return index;
      }
      return -1;
    };
  };

  // Returns the first index on an array-like that passes a predicate test.
  _.findIndex = createPredicateIndexFinder(1);
  _.findLastIndex = createPredicateIndexFinder(-1);

  // Use a comparator function to figure out the smallest index at which
  // an object should be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iteratee, context) {
    iteratee = cb(iteratee, context, 1);
    var value = iteratee(obj);
    var low = 0, high = getLength(array);
    while (low < high) {
      var mid = Math.floor((low + high) / 2);
      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
    }
    return low;
  }; // 二分搜索法

  // Generator function to create the indexOf and lastIndexOf functions.
  var createIndexFinder = function(dir, predicateFind, sortedIndex) {
    return function(array, item, idx) {
      var i = 0, length = getLength(array);
      if (typeof idx == 'number') {
        if (dir > 0) {
          i = idx >= 0 ? idx : Math.max(idx + length, i);
        } else {
          length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
        }
      } else if (sortedIndex && idx && length) {
        idx = sortedIndex(array, item);
        return array[idx] === item ? idx : -1;
      }
      if (item !== item) {
        idx = predicateFind(slice.call(array, i, length), _.isNaN);
        return idx >= 0 ? idx + i : -1;
      }
      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
        if (array[idx] === item) return idx;
      }
      return -1;
    };
  };

  // Return the position of the first occurrence of an item in an array,
  // or -1 if the item is not included in the array.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (stop == null) {
      stop = start || 0;
      start = 0;
    }
    if (!step) {
      step = stop < start ? -1 : 1;
    }

    var length = Math.max(Math.ceil((stop - start) / step), 0);
    var range = Array(length);

    for (var idx = 0; idx < length; idx++, start += step) {
      range[idx] = start;
    }

    return range;
  };

  // Split an **array** into several arrays containing **count** or less elements
  // of initial array.
  _.chunk = function(array, count) {
    if (count == null || count < 1) return [];

    var result = [];
    var i = 0, length = array.length;
    while (i < length) {
      result.push(slice.call(array, i, i += count));
    }
    return result;
  };

今天看来有不少之前看过,而且要回顾的东西。。。。
这里写图片描述

createPredicateIndexFinder

// Generator function to create the findIndex and findLastIndex functions.
  var createPredicateIndexFinder = function(dir) {
    return function(array, predicate, context) {
      predicate = cb(predicate, context);
      var length = getLength(array);
      var index = dir > 0 ? 0 : length - 1;
      for (; index >= 0 && index < length; index += dir) {
        if (predicate(array[index], index, array)) return index;
      }
      return -1;
    };
  };

之前我们只是简略分析过这个函数,现在我们具体划分

一开始的结构:


var createPredicateIndexFinder = function (dir) {
    return function (array, predicate, context) {

    }
} // 构造函数

之后在return 的function内部:

// 传入参数:array, predicate, context
predicate = cb(predicate, context)
var length = getLength(array);
var index = dir > 0 ? 0: length - 1; // 按照dir的正负定义开头在哪里

变量定义完成,接下来就该for循环遍历了


        for (; index >= 0 && index < length; index+=dir) {

        } //+=dir说明dir的大小决定遍历的方式

接下来截取

for (; index >= 0 && index < length; index+=dir) {
            if (predicate(array[index], index, arrray)) return index // 找到则立刻返回真值的index
        }
    return -1; // 找不到则默认返回 -1

一个createPredicateIndexFinder就这样完成了
这里写图片描述

过渡部分

_.findIndex = createPredicateIndexFinder(1); // findIndex从开头一个个找
  _.findLastIndex = createPredicateIndexFinder(-1); // lastIndex从结尾一个个找

_.sortedIndex

// Use a comparator function to figure out the smallest index at which
  // an object should be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iteratee, context) {
    iteratee = cb(iteratee, context, 1);
    var value = iteratee(obj);
    var low = 0, high = getLength(array);
    while (low < high) {
      var mid = Math.floor((low + high) / 2);
      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
    }
    return low;
  };

还是那句话
这里写图片描述

还是拆开分析

_.sortedIndex = function (array, obj, iteratee, context) {

}

没问题,传入四个参数array, obj, iteratee, context
看函数内部:

iteratee = cb(iteratee, context, 1); // 说明iteratee仅传入一个参数
var value = iteratee(obj); // 值的对比
var low = 0, high = getLength(array)) //定义最大值与最小值

while (low < high) {
        var mid = Math.floor((low + high)/2);
        if (iteratee(array[mid]) < value) low = mid + 1; else high = mid
    } //二分搜索

    return low

createIndexFinder

 // Generator function to create the indexOf and lastIndexOf functions.
  var createIndexFinder = function(dir, predicateFind, sortedIndex) {
    return function(array, item, idx) {
      var i = 0, length = getLength(array);
      if (typeof idx == 'number') {
        if (dir > 0) {
          i = idx >= 0 ? idx : Math.max(idx + length, i);
        } else {
          length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
        }
      } else if (sortedIndex && idx && length) {
        idx = sortedIndex(array, item);
        return array[idx] === item ? idx : -1;
      }
      if (item !== item) {
        idx = predicateFind(slice.call(array, i, length), _.isNaN);
        return idx >= 0 ? idx + i : -1;
      }
      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
        if (array[idx] === item) return idx;
      }
      return -1;
    };
  };

结构依然同createPredicateIndexFinder一样


var createIndexFinder = function (dir, predicateFind, sortedIndex) {
    return function (array, item, idx) {

    }
}

传入三个参数array, item, index
生成的函数内部

var i = 0, length = getLength(array);

if (typeof idx == 'number') {
        if (dir > 0) {

        } else {

        }
      } else if (sortedIndex && idx && length) {
        idx = sortedIndex(array, item);
        return array[idx] === item ? idx : -1;
      } //如果idx没有或者为0,且有sortedindex加入,则用二分法
if (typeof idx == 'number') {
        if (dir > 0) {
          i = idx >= 0 ? idx : Math.max(idx + length, i); // 当有index时,index>0, 则取index值
        } else {
          length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; 
        }
      } else if (sortedIndex && idx && length) {
      }

之后有

if (item !== item) {
        idx = predicateFind(slice.call(array, i, length), _.isNaN);
        return idx >= 0 ? idx + i : -1;
      } // 若item = NaN什么的,则单独处理该情况 
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
        if (array[idx] === item) return idx;
      }
      return -1; // 剩余情况

.indexof, .lastIndexOf

// Return the position of the first occurrence of an item in an array,
  // or -1 if the item is not included in the array.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);

_.range

// Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (stop == null) {
      stop = start || 0; //如果不设定stop,那就变为start, 即stop变量提前
      start = 0; //start则变为0
    }
    if (!step) {
      step = stop < start ? -1 : 1;
      // 没有step的时候,则step默认为1,否则如果stop为负,则step为-1
    }

    var length = Math.max(Math.ceil((stop - start) / step), 0);
    var range = Array(length);

    for (var idx = 0; idx < length; idx++, start += step) {
      range[idx] = start;
    }

    return range; //返回range
  };

_.chunk

// Split an **array** into several arrays containing **count** or less elements
  // of initial array.
  _.chunk = function(array, count) {
    if (count == null || count < 1) return [];

    var result = [];
    var i = 0, length = array.length;
    while (i < length) {
      result.push(slice.call(array, i, i += count));
    }
    return result;
  };

这个方法就连官方文档上都没有记录,效果注释上已经解释,分开看

 _.chunk = function(array, count) {
    if (count == null || count < 1) return [];
    // 仅传入数组时或者count < 1时,永远返回一个空数组
    var result = [];
    var i = 0, length = array.length;
    while (i < length) {
      result.push(slice.call(array, i, i += count));
    }
    return result;
  };

该方法也可对字符串使用,用于按数量分割字符串,并入一个数组中,可与_.difference合用。

没了
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值