国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

1625行,解開 underscore.js 的面紗 - 第五章

Rango / 1446人閱讀

摘要:對多個(gè)一維數(shù)組進(jìn)行并運(yùn)算,實(shí)際上就是加強(qiáng)版的。所以我要說的是這個(gè)函數(shù),將傳入?yún)?shù)轉(zhuǎn)換為一個(gè)數(shù)組進(jìn)行到的回調(diào)函數(shù)中,以此達(dá)到函數(shù)接到的是一個(gè)一維數(shù)組的集合。

每次小章節(jié)的開題都煩惱寫什么好,所以直接接下文 (~o▔▽▔)~o o~(▔▽▔o~) 。

  _.first = _.head = _.take = function(array, n, guard) {
    if (array == null) return void 0;
    if (n == null || guard) return array[0];
    return _.initial(array, array.length - n);
  };

_.first 用于返回?cái)?shù)組中從左到右指定數(shù)目 n 的結(jié)果集,傳入 array、n、guard 三個(gè)參數(shù)中 array 只能為 Array,當(dāng) n = null 時(shí)返回?cái)?shù)組第一個(gè)元素,這里需要講解的是 _.initial 函數(shù)是與 _.first 完全對立的函數(shù),它用于返回?cái)?shù)組中從左到右指定數(shù)目 Array.length - n 的結(jié)果集。

  _.initial = function(array, n, guard) {
    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
  };

那么它是如何實(shí)現(xiàn)的呢,依然是應(yīng)用數(shù)組 Array 的 Array.prototype.slice.call(array, start, end); 實(shí)現(xiàn),這個(gè)概念請參看:Array.prototype.slice()。

  _.last = function(array, n, guard) {
    if (array == null) return void 0;
    if (n == null || guard) return array[array.length - 1];
    return _.rest(array, Math.max(0, array.length - n));
  };

_.last 是返回?cái)?shù)組中從右到左指定數(shù)目 n 的結(jié)果集。實(shí)現(xiàn)原理依舊 Array.prototype.slice.call(array, start, end);

  _.rest = _.tail = _.drop = function(array, n, guard) {
    return slice.call(array, n == null || guard ? 1 : n);
  };

_.rest 用于返回?cái)?shù)組中從右到左指定數(shù)目 Array.length - n 的結(jié)果集。

  _.compact = function(array) {
    return _.filter(array, Boolean);
  };

_.compact,我喜歡稱它為過濾器,過濾壞的數(shù)據(jù),那么什么樣的數(shù)據(jù)為壞數(shù)據(jù)呢,我們可以看下 _.filter,前面講 _.filter 接收三個(gè)參數(shù) obj, predicate, context,其中 predicate 依舊由 cb 處理,那么這里 _.compact 傳的 predicate 是 Boolean = function Boolean() { [native code] },這是一個(gè) JAVASCRIPT 內(nèi)置的函數(shù)用于 Boolean 判斷,我們可以參考 Boolean 和 Boolean data type。那么重點(diǎn)來了,什么的值會是 Boolean 函數(shù)斷言為 false 呢,答案就是 false, 0, "", null, undefined, NaN,這個(gè)可不是我瞎說或者 copy 官網(wǎng),我是有理論依據(jù)的(v?v),當(dāng)當(dāng)當(dāng),看這里 Truthy。

  var flatten = function(input, shallow, strict, output) {
    output = output || [];
    var idx = output.length;
    for (var i = 0, length = getLength(input); i < length; i++) {
      var value = input[i];
      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
        if (shallow) {
          var j = 0, len = value.length;
          while (j < len) output[idx++] = value[j++];
        } else {
          flatten(value, shallow, strict, output);
          idx = output.length;
        }
      } else if (!strict) {
        output[idx++] = value;
      }
    }
    return output;
  };

flatten 傳入四個(gè)參數(shù),input, shallow, strict, output,其中我們可以通過 flatten 內(nèi)部的 for 循環(huán)中 length = getLength(input); 知道 input 數(shù)據(jù)類型為 Array。然后通過對 shallow, strict 兩個(gè) Boolean 型變量的控制執(zhí)行相應(yīng)的數(shù)據(jù)處理方式。比如 shallow 為 false 會一直執(zhí)行 flatten(value, shallow, strict, output);output[idx++] = value; 對多維數(shù)組進(jìn)行一維數(shù)組的轉(zhuǎn)換。

  _.flatten = function(array, shallow) {
    return flatten(array, shallow, false);
  };

_.flatten 函數(shù)用于對多維度數(shù)組進(jìn)行扁平化處理,即將任意維數(shù)的數(shù)組轉(zhuǎn)換為一維數(shù)組,上面已經(jīng)說到了這個(gè)的實(shí)現(xiàn)方式。

  _.without = restArgs(function(array, otherArrays) {
    return _.difference(array, otherArrays);
  });

_.without 用于刪除數(shù)組中的某些特定元素。它由 _.difference 構(gòu)成。

  _.uniq = _.unique = function(array, isSorted, iteratee, context) {
    if (!_.isBoolean(isSorted)) {
      context = iteratee;
      iteratee = isSorted;
      isSorted = false;
    }
    if (iteratee != null) iteratee = cb(iteratee, context);
    var result = [];
    var seen = [];
    for (var i = 0, length = getLength(array); i < length; i++) {
      var value = array[i],
          computed = iteratee ? iteratee(value, i, array) : value;
      if (isSorted) {
        if (!i || seen !== computed) result.push(value);
        seen = computed;
      } else if (iteratee) {
        if (!_.contains(seen, computed)) {
          seen.push(computed);
          result.push(value);
        }
      } else if (!_.contains(result, value)) {
        result.push(value);
      }
    }
    return result;
  };

_.uniq 是數(shù)組去重,實(shí)現(xiàn)原理是如果 isSorted 及后面元素省略,那么 _.uniq 簡化為:

    _.uniq = _.unique = function(array) {
        context = null;
        iteratee = null;
        isSorted = false;
        var result = [];
        var seen = [];
        for (var i = 0, length = getLength(array); i < length; i++) {
          var value = array[i];
          if (!_.contains(result, value)) {
            result.push(value);
          }
        }
        return result;
      };

我們可以看到其核心代碼只有 if (!_.contains(result, value)),用于判斷數(shù)組中是否包含其值,以此達(dá)到數(shù)組去重的目的。是這里我想說的是 context、iteratee、isSorted 變成了未定義的參數(shù),作者沒有處理它會在這種情況下變成全局污染。
接下來我們說一下傳入 array, isSorted, iteratee 三個(gè)參數(shù)的情況,我們已經(jīng)知道 isSorted 默認(rèn)為 false,代表去重,那么如果定義 isSorted 為 true 則就是不去重,如果 isSorted 是回調(diào)函數(shù),則默認(rèn)內(nèi)部重新定義 isSorted 為 false,并將回調(diào)函數(shù)賦給 iteratee,然后很悲劇的 iteratee 參數(shù)依然是沒有 var 過的,又污染了啊(?_??) 。大致就是這醬了。

  _.union = restArgs(function(arrays) {
    return _.uniq(flatten(arrays, true, true));
  });

_.union 對多個(gè)一維數(shù)組進(jìn)行并運(yùn)算,實(shí)際上就是加強(qiáng)版的 _.uniq。在代碼中作者首先用 flatten 函數(shù)處理參數(shù),之前我們說到 flatten 是用于多個(gè)多維數(shù)組進(jìn)行一位轉(zhuǎn)換,實(shí)際上就是要把 arrays 轉(zhuǎn)換。這里有同學(xué)可能問道 flatten 直接收一個(gè) Array 剩下的值是 Boolean 啊,那么使用 _.union 的時(shí)候是一次性傳入 n 個(gè) Array(如這樣:_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);),說不通啊。所以我要說的是 restArgs 這個(gè)函數(shù),將傳入?yún)?shù)轉(zhuǎn)換為一個(gè)數(shù)組進(jìn)行 func.apply(this, args) 到 restArgs 的回調(diào)函數(shù) function(arrays) {} 中,以此達(dá)到 flatten 函數(shù) arrays 接到的是一個(gè)一維數(shù)組的集合。最后通過 _.uniq 函數(shù)對數(shù)組進(jìn)行處理。

  _.intersection = function(array) {
    var result = [];
    var argsLength = arguments.length;
    for (var i = 0, length = getLength(array); i < length; i++) {
      var item = array[i];
      if (_.contains(result, item)) continue;
      var j;
      for (j = 1; j < argsLength; j++) {
        if (!_.contains(arguments[j], item)) break;
      }
      if (j === argsLength) result.push(item);
    }
    return result;
  };

_.intersection 用于獲取多個(gè)一維數(shù)組的相同數(shù)據(jù)的集合,即交集。又是一番對 Array 的 for 啊 for 啊 for,然后 if 然后 push,相信大家這么聰明,不用多說了,因?yàn)檫@個(gè)函數(shù)很直白,沒太多可講的。

  _.difference = restArgs(function(array, rest) {
    rest = flatten(rest, true, true);
    return _.filter(array, function(value){
      return !_.contains(rest, value);
    });
  });

_.difference 函數(shù)的實(shí)現(xiàn)與 _.union 類似,都是通過 restArgs 對 n 個(gè)傳參進(jìn)行數(shù)組轉(zhuǎn)變,然后賦給回調(diào)函數(shù),區(qū)別在于這個(gè)函數(shù)可能更加復(fù)雜,它首先 restArgs 回調(diào)寫了兩個(gè)傳參 array, rest,但實(shí)際上 rest 是 undefined,之后在回調(diào)內(nèi)部給 rest 賦值為 flatten 函數(shù)處理之后的數(shù)組,即扁平化后的一維數(shù)組。因?yàn)?restArgs 函數(shù)只有一個(gè) function 回調(diào),所以內(nèi)部執(zhí)行 return func.call(this, arguments[0], rest);,返回的是第一個(gè)數(shù)組和其他數(shù)組的集合,即 array, rest

  _.unzip = function(array) {
    var length = array && _.max(array, getLength).length || 0;
    var result = Array(length);
    for (var index = 0; index < length; index++) {
      result[index] = _.pluck(array, index);
    }
    return result;
  };

_.unzip 用于將多個(gè)數(shù)組中元素按照數(shù)組下標(biāo)進(jìn)行拼接,只接收一個(gè)二維數(shù)組,返回值同樣是一個(gè)二維數(shù)組。

  _.zip = restArgs(_.unzip);

_.zip_.unzip 不同之處在于它可以傳入不定的一維數(shù)組參數(shù)然后通過 restArgs 函數(shù)轉(zhuǎn)換實(shí)現(xiàn) _.unzip 傳參的效果。

  _.object = function(list, values) {
    var result = {};
    for (var i = 0, length = getLength(list); i < length; i++) {
      if (values) {
        result[list[i]] = values[i];
      } else {
        result[list[i][0]] = list[i][1];
      }
    }
    return result;
  };

_.object 用于將數(shù)組轉(zhuǎn)換成對象。

  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;
    };
  };

createPredicateIndexFinder 這個(gè)函數(shù)適用于生成 _.findIndex 之類的函數(shù),當(dāng)我們看到 return index; 的是后就已經(jīng)可以知道,其核心是與數(shù)組下標(biāo)有關(guān)。

  _.findIndex = createPredicateIndexFinder(1);

_.findIndex 函數(shù)由 createPredicateIndexFinder 包裝而成,我們可以看到它的默認(rèn)傳值是 1,也就是:

    _.findIndex = function(array, predicate, context) {
       predicate = cb(predicate, context);
       for (var index >= 0; index < getLength(array); index += 1) {
           if (predicate(array[index], index, array)) return index;
       }
       return -1;
   };

其中 predicate 是回調(diào)函數(shù)接收 array[index], index, array 三個(gè)值用于 Boolean 判斷,最終結(jié)果是返回符合規(guī)則的數(shù)組中的第一條數(shù)據(jù)的數(shù)組下標(biāo)。

  _.findLastIndex = createPredicateIndexFinder(-1);

_.findLastIndex 顧名思義就是返回?cái)?shù)組中符合規(guī)則的最后一條數(shù)據(jù)的下標(biāo),說直白了就是遍歷數(shù)組的時(shí)候從右往左而已。

  _.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 官網(wǎng)解釋說 使用二分查找確定value在list中的位置序號,value按此序號插入能保持list原有的排序。,很繞口,這里我們需要注意的是如果進(jìn)行 _.sortedIndex 查找這個(gè)特定的序列號,一定要事先將 array 進(jìn)行按需排序。

  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;
    };
  };

createIndexFinder,看命名就可以知道依舊與數(shù)組下標(biāo)有關(guān)。我們可以看到數(shù)據(jù)處理的一個(gè)關(guān)鍵是 idx,它可能是一個(gè)數(shù)字也可能是一個(gè)字符串或者對象。當(dāng)它是 Number 的時(shí)候遵循 idx 是限制查找范圍的數(shù)組下標(biāo)規(guī)則,如果它是其他的則使用 sortedIndex 函數(shù)查找到 idx 的數(shù)組下標(biāo)再歲數(shù)組查找范圍進(jìn)行限定。

  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);

_.indexOf 函數(shù)與 _.findIndex 區(qū)別在于 _.findIndex 需要查找的數(shù)據(jù)可能存在于數(shù)組中也可能不存在數(shù)組中,而 _.indexOf 的 predicateFind 一定是數(shù)組中的元素。同時(shí)也用 array, item, idx 三個(gè)參數(shù)中的 idx 限定開始查找的范圍。

  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);

_.lastIndexOf 查找數(shù)組中的符合結(jié)果的最后條數(shù)據(jù)的數(shù)組下標(biāo)。

  _.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;
  };

_.range 用于生成一個(gè)有序的數(shù)組,通過 start 和 stop 限定數(shù)組范圍,通過 step 限定差值。

  _.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,這個(gè)函數(shù)目前官網(wǎng)并沒有釋義,估計(jì)作者忘記加進(jìn)去了吧,我們看到 chunk 很自然的就應(yīng)該想到 stream 的概念,這里也差不多,只不過拆分的不限定是 Buffer 數(shù)組, _.chunk 傳入兩個(gè)參數(shù) Array 以及 count,其中 count 用來限定拆分出的每一組的大小,舉個(gè)栗子:

   _.chunk([1,2,3,4,5,6,7,8,9], 1)
   [[1],[2],[3],[4],[5],[6],[7],[8],[9]]
   _.chunk([1,2,3,4,5,6,7,8,9], 2)
   [[1,2],[3,4],[5,6],[7,8],[9]]

然而但凡對 stream 的概念有所了解都知道這個(gè)函數(shù)吧,沒什么特殊的地方。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86341.html

相關(guān)文章

  • 如何自制 JS 注釋文檔生成工具

    摘要:組件的選擇命令行工具首先我們需要一個(gè)命令行工具來方便的執(zhí)行命令,這里我們選擇組件,如果不喜歡使用且有能力的人完全可以通過組件自己封裝執(zhí)行命令函數(shù)。 對于一個(gè)成熟的項(xiàng)目而言,一定需要一個(gè)注釋文檔生成工具,我們有很多可選的開源項(xiàng)目,如jsdoc、yuidocjs 等等,擁有這些強(qiáng)大的工具我們完全可以勝任任何注釋方面的管理了么? 一個(gè)成熟的開發(fā)者都會知道不管怎么樣的項(xiàng)目都會在不同的開發(fā)條件下...

    Cristalven 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第一章

    摘要:新出臺的則規(guī)定,包括六種原始類型和,還有一種,詳見數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)。用于返回一個(gè)由給定對象的所有可枚舉自身屬性的屬性名組成的數(shù)組,。接下來判斷數(shù)字進(jìn)行相應(yīng)的操作,其中有和兩個(gè)方法,詳見和。 一直想寫一篇這樣的文章,于是心動(dòng)不如行動(dòng),這里選擇的是 Underscore.js 1.8.3 版本,源碼注釋加在一起1625行。 Underscore.js 1.8.3 http://unde...

    MockingBird 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第二章

    摘要:第四個(gè)判斷如果是對象執(zhí)行返回一個(gè)斷言函數(shù),用來判定傳入對象是否匹配指定鍵值屬性。都不匹配最后執(zhí)行,返回傳入的對象的屬性。設(shè)置的值并生成函數(shù),等同于,使具有屬性且有值則返回,否則返回,這是一個(gè)判斷函數(shù)。 在第二小章節(jié)里面我按照源碼順序介紹幾個(gè)方法,源碼緊接著第一章繼續(xù): var builtinIteratee; builtinIteratee,內(nèi)置的 Iteratee (迭代器)。...

    yuxue 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第四章

    摘要:接收三個(gè)參數(shù)分別為回調(diào)和,其中與是可選參數(shù)。官網(wǎng)釋義排序一個(gè)列表組成一個(gè)組,并且返回各組中的對象的數(shù)量的計(jì)數(shù)。類似,但是不是返回列表的值,而是返回在該組中值的數(shù)目。 繼續(xù)前面的內(nèi)容,前文我們提到了很多方法的講解,其實(shí)到這里就已經(jīng)差不多了,因?yàn)榇蟛糠执a其實(shí)都是套路,一些基礎(chǔ)函數(shù)再靈活變化就可以組成很多實(shí)用的功能。 _.sortBy = function(obj, iteratee,...

    zhaochunqi 評論0 收藏0
  • 1625解開 underscore.js 面紗 - 第三章

    摘要:傳入值進(jìn)行判斷以此決定函數(shù),將三個(gè)參數(shù)包括回調(diào)傳入中其中回調(diào)函數(shù)充當(dāng)?shù)鬟M(jìn)行真值檢測,最后。是從一個(gè)中隨機(jī)返回值,并且返回值受限于這個(gè)參數(shù),如果沒有傳入或者傳入了則執(zhí)行語句,目的是將判斷處理之后返回單一值。 今天繼續(xù)上次的內(nèi)容,之前我們講到了 reduce 的用法,其實(shí)我覺得用法倒是其次的關(guān)鍵是作者實(shí)現(xiàn) reduce 過程中所靈活用到的函數(shù)處理方法,我們只要有心稍加總覺完全可以拿來主...

    dack 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<