现在的位置: 首页 > 综合 > 正文

源码学习—-underscore

2014年11月03日 ⁄ 综合 ⁄ 共 1461字 ⁄ 字号 评论关闭

以前在网上做过一个面试题,在一个有序的数组查找特定值,如果存在返回数组下标,否则将数值插入数组中。我的之前做法在这里!

通过进一步学习underscoreJS,发现可以这么写

var arr = [10,20,30], value = 35;
var location = _.sortIndex( arr, value);
arr[location] == value || arr.splice( location, 0, value); 

如上所示,代码简单了很多!那效率究竟怎么样呢?看到underscore的源码发现源码中利用的是二分查找,时间复杂度是logn,而我那个就是n,差了不仅一点点。

为什么underscore这么好?因为它关注重点,功能专一

_.sortedIndex = function(array, obj, iterator, context) {
    iterator = lookupIterator(iterator);
    var value = iterator.call(context, obj);
    var low = 0, high = array.length;
    while (low < high) {
      var mid = (low + high) >>> 1;
      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;//why?
    }
    return low;
  };

上面的代码为什么这么写?难道是保留上下文才这么写的吗?在上面的代码中至少学到了

1.位运算;

2.函数递归调用与闭包的使用。


第二点  each方法的使用

在underscore.js中很多的函数都是为集合服务的,里面包括很多的迭代操作!

var each = _.each = _.forEach = function(obj, iterator, context) {
    if (obj == null) return obj;
    if (nativeForEach && obj.forEach === nativeForEach) {//nativeForEach
      obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {//array
      for (var i = 0, length = obj.length; i < length; i++) {
        if (iterator.call(context, obj[i], i, obj) === breaker) return;
      }
    } else {//object
      var keys = _.keys(obj);
      for (var i = 0, length = keys.length; i < length; i++) {
        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
      }
    }
    return obj;
  };

函数中首先定义局部变量,在作用域下方便使用。

1.使用本地的forEach的方法。

2.判断数组的情况

3.判断对象的情况。判断对象的情况的时候特别有意思的一点,它没有像jQuery在对象中为每个对象给出0,1,2,3等属性,而是将属性存为属性数组,

然后遍历‘属性数组’,取出对象中属性对应的值。

_.keys = function(obj) {
    if (!_.isObject(obj)) return [];
    if (nativeKeys) return nativeKeys(obj);
    var keys = [];
    for (var key in obj) if (_.has(obj, key)) keys.push(key);
    return keys;
  };

抱歉!评论已关闭.