亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

1625行,解開(kāi) underscore.js 的面紗 - 第三章

dack / 964人閱讀

摘要:傳入值進(jìn)行判斷以此決定函數(shù),將三個(gè)參數(shù)包括回調(diào)傳入中其中回調(diào)函數(shù)充當(dāng)?shù)鬟M(jìn)行真值檢測(cè),最后。是從一個(gè)中隨機(jī)返回值,并且返回值受限于這個(gè)參數(shù),如果沒(méi)有傳入或者傳入了則執(zhí)行語(yǔ)句,目的是將判斷處理之后返回單一值。

今天繼續(xù)上次的內(nèi)容,之前我們講到了 reduce 的用法,其實(shí)我覺(jué)得用法倒是其次的關(guān)鍵是作者實(shí)現(xiàn) reduce 過(guò)程中所靈活用到的函數(shù)處理方法,我們只要有心稍加總覺(jué)完全可以拿來(lái)主義,豐富自己的代碼└(^o^)┘。

 _.find = _.detect = function(obj, predicate, context) {
    var keyFinder = isArrayLike(obj) ? _.findIndex : _.findKey;
    var key = keyFinder(obj, predicate, context);
    if (key !== void 0 && key !== -1) return obj[key];
  };

_.find,討論這個(gè)函數(shù)首先要弄懂 _.findIndex_.findKey,這里我們先簡(jiǎn)單知道一個(gè)是針對(duì)數(shù)組一個(gè)是針對(duì)對(duì)象,具體的后面讀到源碼再說(shuō)。傳入值 obj 進(jìn)行 isArrayLike 判斷以此決定 keyFinder 函數(shù),將三個(gè)參數(shù)包括回調(diào)傳入 keyFinder 中其中 predicate 回調(diào)函數(shù)充當(dāng)?shù)鬟M(jìn)行真值檢測(cè),最后 return obj[key]。

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

_.findIndex 為例簡(jiǎn)單介紹一下,_.findIndex 是由 createPredicateIndexFinder 包裝而成,意義在于返回 predicate 函數(shù)內(nèi)部 return true。

  _.filter = _.select = function(obj, predicate, context) {
    var results = [];
    predicate = cb(predicate, context);
    _.each(obj, function(value, index, list) {
      if (predicate(value, index, list)) results.push(value);
    });
    return results;
  };

_.filter 函數(shù)與 _.find 類似,內(nèi)部實(shí)現(xiàn)較之 _.find 更簡(jiǎn)單些,_.find 意為匹配 predicate 回調(diào) return true 唯一就近值,_.filter 則是匹配所有值的集合。那么有人說(shuō)為什么不用 _.filter()[0] 取代 _.find,理論上二者確實(shí)是相同值,但是 _.filter 會(huì)遍歷傳參 obj 直至結(jié)束,而 _.find 則是遍歷過(guò)程中匹配成功結(jié)束遍歷,所以某些情況下 _.find 優(yōu)于 _.filter。

  _.reject = function(obj, predicate, context) {
    return _.filter(obj, _.negate(cb(predicate)), context);
  };

_.reject,通過(guò) _.negatecb 函數(shù)包裝 predicate 回調(diào),實(shí)際上就是用 optimizeCb 優(yōu)化 predicate function,然后用 _.negate 返回與 predicate 相反的 Boolean 類型值,以此獲得與 _.filter 作用相反的結(jié)果集合。

  _.every = _.all = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length;
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      if (!predicate(obj[currentKey], currentKey, obj)) return false;
    }
    return true;
  };

_.every,我們看源碼中的返回值類型為 Boolean 知道這是一個(gè)用于真值檢測(cè)的函數(shù),內(nèi)部的處理步驟已經(jīng)很程序化了,首先優(yōu)化回調(diào)函數(shù) predicate,處理傳參 obj(根據(jù) Object 或者 Array),回調(diào)中接收 obj[currentKey], currentKey, obj 三個(gè)參數(shù)進(jìn)行 Boolean 判斷,當(dāng)判斷失敗的時(shí)候則 if (!false) return false; 結(jié)束 for 循環(huán)。這個(gè)方法看上去很雞肋,但實(shí)際上結(jié)合 predicate 回調(diào)應(yīng)用于某些判斷處理很給力。

  _.some = _.any = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length;
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      if (predicate(obj[currentKey], currentKey, obj)) return true;
    }
    return false;
  };

_.some,看源碼我們可以知道它基本上與 _.every 類似,區(qū)別在于 _.some 遍歷 obj 過(guò)程中只要任何一個(gè)元素通過(guò) predicate 回調(diào)的真值檢測(cè)就直接立即中斷遍歷并返回 true。我主觀意識(shí)上更偏向于 _.every_.some 用一個(gè)相同的基礎(chǔ)函數(shù)包裝再通過(guò)判斷值構(gòu)建它們,就像 createReduce 函數(shù)構(gòu)成 _.reduce、_.reduceRight 一樣,但是不知道作者為什么沒(méi)有這樣做,可能有其他的考慮吧,這里不再揣測(cè)。

  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
    if (!isArrayLike(obj)) obj = _.values(obj);
    if (typeof fromIndex != "number" || guard) fromIndex = 0;
    return _.indexOf(obj, item, fromIndex) >= 0;
  };

_.contains 用于檢查 obj 中是否包含 item 值,我更傾向于這是一個(gè)簡(jiǎn)化版的 _.some,如果是我寫基礎(chǔ)函數(shù)可能真的就只有 _.some 不用 _.contains,但是 Undescore.js 作為一個(gè)知名函數(shù)庫(kù),在代碼優(yōu)化的執(zhí)行速度上肯定要比我們做的更細(xì)。
這里順便說(shuō)一下 _.indexOfguard,_.indexOf 是由 createIndexFinder 包裝而來(lái),可以理解為數(shù)組版的 indexOf,indexOf 概念可參考 String.prototype.indexOf() 和 Array.prototype.indexOf()。關(guān)于 array.indexOf(searchElement[, fromIndex = 0]),我這里再說(shuō)幾句,這個(gè) JAVASCRIPT 函數(shù)傳入1或2個(gè)參數(shù),第一個(gè)參數(shù)為將要進(jìn)行匹配的內(nèi)容,可為 Number 可為 String,第二個(gè)可選參數(shù)為(需要定向匹配數(shù)組中某一值的數(shù)組下標(biāo)值 - array.length)*n,且 n!= 0,array.indexOf 根據(jù)這個(gè)下標(biāo)進(jìn)行定向匹配驗(yàn)證,如果匹配成功則返回值為被匹配值的數(shù)組下標(biāo),匹配失敗則返回 -1。

    var array = [2, 9, 9,9,9,3,4];
    undefined
    array.indexOf(9,2);
    2
    array.indexOf(9,3);
    3
    array.indexOf(9,4);
    4
    array.indexOf(9,5);
    -1
    array.indexOf(3,5);
    5
    array.indexOf(5);
    -1
    array.indexOf(2, -7);
    0

_.indexOf 雖然與 array.indexOf(searchElement[, fromIndex = 0]) 有所區(qū)別,但也有很多相通之處。

  _.invoke = restArgs(function(obj, method, args) {
    var isFunc = _.isFunction(method);
    return _.map(obj, function(value) {
      var func = isFunc ? method : value[method];
      return func == null ? func : func.apply(value, args);
    });
  });

_.invoke 用于批量執(zhí)行方法,前面我們講了 restArgs 方法,雖然代碼很復(fù)雜,但目前實(shí)際上只應(yīng)用了如下簡(jiǎn)化的結(jié)構(gòu):

  var restArgs = function(func) {
    return function() {
      return func.apply(this, arguments);
    };
  };

也就是說(shuō) _.invoke 拋開(kāi)閉包的概念之后等同于:

    function(obj, method, args) {
        var isFunc = _.isFunction(method);
        return _.map(obj, function(value) {
          var func = isFunc ? method : value[method];
          return func == null ? func : func.apply(value, args);
        });
      }

其中 _.isFunction 是判斷是否為 function,接下來(lái) _.map 回調(diào),實(shí)際上我很納悶萬(wàn)一傳入的 method 是 obj[i] 對(duì)象上沒(méi)有的方法怎么辦,按照 return 的結(jié)果如果沒(méi)有則返回 func 也就是 null,總覺(jué)得這樣返回缺少點(diǎn)什么。

  _.pluck = function(obj, key) {
    return _.map(obj, _.property(key));
  };

_.pluck 返回傳入 obj 的 key 的集合,或者說(shuō) key 的集合有點(diǎn)武斷,更具體點(diǎn)說(shuō)是 obj 下第二層所包含 key 的值的集合,而第一層也就是 obj 可為 Object 或 Array,但 obj 中第二層必須是 Object。這是為什么呢?

    _.map(obj, function(key) {
        return (function(obj) {
          return obj == null ? void 0 : obj[key];
        })(key);
      })

在上述簡(jiǎn)化的代碼中我們可以看出 return obj == null ? void 0 : obj[key]; 的值是 obj[key],所以第二層只能是 Object。

  _.where = function(obj, attrs) {
    return _.filter(obj, _.matcher(attrs));
  };

_.where 很有趣,代碼簡(jiǎn)化之后是:

  _.where = function(obj, attrs) {
    return _.filter(obj, (function(attrs) {
        attrs = _.extendOwn({}, attrs);
        return function(obj) {
          return _.isMatch(obj, attrs);
        })(attrs);
      });
  };

_.filter 我們講過(guò)是獲取所有匹配值的集合,而回調(diào)中的 _.extendOwn 將 attrs 放入空對(duì)象 {} 中并 return,_.isMatch是個(gè)斷言用于判斷 obj 中是否存在 key-value。那么 _.where 就是 _.isMatch_.filter 的加強(qiáng)版,它用于判斷一個(gè)大的對(duì)象數(shù)組中存在與傳入 attrs 相同的鍵值對(duì),如果存在則返回匹配目標(biāo)鍵值對(duì)所在的 Object,并且返回值是一個(gè)集合。

    var list = [{author:"Shakespeare",title:"china"},
        {author:"Shakespeare",year:1611,title:"china"},
        {author:"Shakespeare",year:1611,title:"English"},
        {year:1611,title:"china"}];
    _.where(list, {author: "Shakespeare", year: 1611});
    [{"author":"Shakespeare","year":1611,"title":"china"},{"author":"Shakespeare","year":1611,"title":"English"}]

這個(gè)方法在處理數(shù)據(jù)的時(shí)候特別有用。

  _.findWhere = function(obj, attrs) {
    return _.find(obj, _.matcher(attrs));
  };

_.findWhere,相當(dāng)于 _.where()[0],即返回結(jié)果集合的第一個(gè)值,這么設(shè)定的目的和 _.find_.filter 一樣,運(yùn)算更快,遍歷到目標(biāo)馬上停止遍歷。

  _.max = function(obj, iteratee, context) {
    var result = -Infinity, lastComputed = -Infinity,
        value, computed;
    if (iteratee == null || (typeof iteratee == "number" && typeof obj[0] != "object") && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value != null && value > result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(v, index, list) {
        computed = iteratee(v, index, list);
        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
          result = v;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

_.max 用來(lái)查找 obj 對(duì)象數(shù)組中某一 key 的最大值的 Object,限定是 key-value 的 value 必須是 Number 類型。-Infinity 我更喜歡叫它負(fù)無(wú)窮,這里的 if true 第一個(gè)判斷可以忽略了,為什么不講了呢,因?yàn)樽髡咭艞?typeof iteratee == "number" && typeof obj[0] != "object" 這種情況,可見(jiàn)其他版本的 Underscore.js。如果忽略 typeof iteratee == "number" && typeof obj[0] != "object" 的情況則 _.max 傳參為一個(gè)數(shù)組,return 為數(shù)組中最大值。if false 則進(jìn)行常規(guī)的 _.each 代碼很簡(jiǎn)單這里不再講解。

  _.min = function(obj, iteratee, context) {
    var result = Infinity, lastComputed = Infinity,
        value, computed;
    if (iteratee == null || (typeof iteratee == "number" && typeof obj[0] != "object") && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value != null && value < result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(v, index, list) {
        computed = iteratee(v, index, list);
        if (computed < lastComputed || computed === Infinity && result === Infinity) {
          result = v;
          lastComputed = computed;
        }
      });
    }
    return result;
  };

_.min 真心不用講了,參考 _.max

  _.shuffle = function(obj) {
    return _.sample(obj, Infinity);
  };

_.shuffle 官網(wǎng)釋義是返回一個(gè)隨機(jī)亂序的 list 副本, 使用 Fisher-Yates shuffle 來(lái)進(jìn)行隨機(jī)亂序.,Fisher-Yates shuffle 是什么鬼,我們這里看到 _.shuffle 這個(gè)函數(shù)用到了 _.sample,所以我們先講 _.sample。

  _.sample = function(obj, n, guard) {
    if (n == null || guard) {
      if (!isArrayLike(obj)) obj = _.values(obj);
      return obj[_.random(obj.length - 1)];
    }
    var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj);
    var length = getLength(sample);
    n = Math.max(Math.min(n, length), 0);
    var last = length - 1;
    for (var index = 0; index < n; index++) {
      var rand = _.random(index, last);
      var temp = sample[index];
      sample[index] = sample[rand];
      sample[rand] = temp;
    }
    return sample.slice(0, n);
  };

_.sample 是從一個(gè) obj 中隨機(jī)返回值,并且返回值受限于 n 這個(gè)參數(shù),如果沒(méi)有傳入 n 或者傳入了 guard = true 則執(zhí)行 if 語(yǔ)句,目的是將 obj 判斷處理之后返回單一值。這里覺(jué)得特雞肋有木有,也就是說(shuō) _.sample(obj,n,true)_.sample(obj) 是一回事。如果按照 _.sample(obj,n) 的邏輯執(zhí)行,依賴是老套路,處理 obj (Object 和 Array),然后 n = Math.max(Math.min(n, length), 0); 獲得合理的 n 值,前面我們講到了 Infinity 正無(wú)窮和 -Infinity 負(fù)無(wú)窮,這段代碼利用了 Infinity 的特性包裝了 _.shuffle函數(shù),關(guān)鍵就是 Infinity 大于所有 Number 數(shù)字,即 Math.min(Infinity, Number) 等于 Number,好處就是讓人眼前一亮,哇,原來(lái)代碼還可以這樣寫,壞處就是當(dāng)多帶帶使用 _.sample 函數(shù)的 n 大于處理之后的 obj 的長(zhǎng)度時(shí)并不會(huì)報(bào)錯(cuò),而是默認(rèn)執(zhí)行 n=sample.length,仁者見(jiàn)仁,智者見(jiàn)智吧。后面就是很套路的根據(jù)數(shù)組下標(biāo)替換數(shù)組內(nèi)容,當(dāng)然數(shù)組下標(biāo)是通過(guò) _.random 隨機(jī)的,然后 slice 一刀切數(shù)組。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/86328.html

相關(guān)文章

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

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

    Cristalven 評(píng)論0 收藏0
  • 1625解開(kāi) underscore.js 面紗 - 第一章

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

    MockingBird 評(píng)論0 收藏0
  • 1625,解開(kāi) underscore.js 面紗 - 第二章

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

    yuxue 評(píng)論0 收藏0
  • 1625,解開(kāi) underscore.js 面紗 - 第四章

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

    zhaochunqi 評(píng)論0 收藏0
  • 1625解開(kāi) underscore.js 面紗 - 第六章

    摘要:用來(lái)構(gòu)成和兩個(gè)函數(shù),主要針對(duì)的是為了將函數(shù)調(diào)用模式更改為構(gòu)造器調(diào)用和方法調(diào)用。通過(guò)函數(shù)設(shè)定時(shí)間為毫秒后執(zhí)行函數(shù)的回調(diào)函數(shù),用以達(dá)到在規(guī)定時(shí)間毫秒時(shí)執(zhí)行函數(shù)的目的,并且規(guī)定時(shí)間內(nèi)只執(zhí)行一次函數(shù)。 北京的雨已經(jīng)斷斷續(xù)續(xù)下了好久,昏昏欲睡的躲在家里不愿意出門,火影忍者快要結(jié)束了,一拳超人第二季據(jù)說(shuō)還要等好多年,勇者大冒險(xiǎn)貌似斷更了,我又是在不喜歡海賊王的畫風(fēng),所以,我該看什么好呢。 va...

    v1 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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