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

資訊專欄INFORMATION COLUMN

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

yuxue / 1314人閱讀

摘要:第四個判斷如果是對象執(zhí)行返回一個斷言函數(shù),用來判定傳入對象是否匹配指定鍵值屬性。都不匹配最后執(zhí)行,返回傳入的對象的屬性。設(shè)置的值并生成函數(shù),等同于,使具有屬性且有值則返回,否則返回,這是一個判斷函數(shù)。

在第二小章節(jié)里面我按照源碼順序介紹幾個方法,源碼緊接著第一章繼續(xù):

  var builtinIteratee;

builtinIteratee,內(nèi)置的 Iteratee (迭代器)。

  var cb = function(value, context, argCount) {
    if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
    if (value == null) return _.identity;
    if (_.isFunction(value)) return optimizeCb(value, context, argCount);
    if (_.isObject(value)) return _.matcher(value);
    return _.property(value);
  };

cb 函數(shù)接受三個參數(shù),陸續(xù)四個判斷,第一個判斷 _.iteratee,根據(jù) JAVASCRIPT 的上下文,首先 builtinIteratee 為 undefined,然 cb 函數(shù)內(nèi) builtinIteratee 為 undefined,接下來就是 _.iteratee = builtinIteratee 里面的 cb 函數(shù),so...接著第二個判斷傳入?yún)?shù)是否為空值,如果是則返回 _.identity 函數(shù),即當(dāng)前傳入值。第三個判斷傳入值是方法則執(zhí)行 optimizeCb 函數(shù)。第四個判斷如果是對象執(zhí)行返回一個斷言函數(shù),用來判定傳入對象是否匹配attrs指定鍵/值屬性。都不匹配最后執(zhí)行 _.property,返回傳入的對象的 key 屬性。

  _.iteratee = builtinIteratee = function(value, context) {
    return cb(value, context, Infinity);
  };

_.iteratee 這個函數(shù)一般認(rèn)為是一個迭代器,這里是作者的主觀寫法,因為從意義上講, cb 函數(shù)和 _.iteratee 函數(shù)很相似,甚至說只要稍加改動 cb 完全可以替換掉 _.iteratee,作者用 _.iteratee 包裝 cb 并提供外部訪問,雖然實際工作中我們運(yùn)用 _.iteratee 函數(shù)并不常見,但如果用的好絕對是一利器,由 underscore.js 源碼內(nèi)部隨處可見的 cb(),就知道這一函數(shù)的作用之大。在 underscorereturn cb() 傳入了第三個參數(shù) Infinity,意為參數(shù)類型為 Infinity 當(dāng)執(zhí)行第三個 cb 函數(shù)的 if 判斷,執(zhí)行 return optimizeCb(); 時就會發(fā)揮其作用,Infinity 類型也蠻有意思,有興趣的同學(xué)可以參考 Infinity、POSITIVE_INFINITY 和 NEGATIVE_INFINITY。

  var restArgs = function(func, startIndex) {
    startIndex = startIndex == null ? func.length - 1 : +startIndex;
    return function() {
      var length = Math.max(arguments.length - startIndex, 0);
      var rest = Array(length);
      for (var index = 0; index < length; index++) {
        rest[index] = arguments[index + startIndex];
      }
      switch (startIndex) {
        case 0: return func.call(this, rest);
        case 1: return func.call(this, arguments[0], rest);
        case 2: return func.call(this, arguments[0], arguments[1], rest);
      }
      var args = Array(startIndex + 1);
      for (index = 0; index < startIndex; index++) {
        args[index] = arguments[index];
      }
      args[startIndex] = rest;
      return func.apply(this, args);
    };
  };

restArgs(其余的參數(shù)),什么意思呢,我們看它傳入了一個 function 和 一個 Number 類型的 startIndex 標(biāo)識,首先處理的是 startIndex。三元運(yùn)算判斷 startIndex 是否存在,是則為 +startIndex,否則為 func.length - 1 即傳入 function 中的傳入形參的數(shù)量減一,舉個例子如:

  var aFunction = function(a,b,c){};
  function(a){
      console.log(a.length)    //3
  }

這么做的目的是什么呢,我們都知道在一個 Array 中數(shù)組排序是從 0 開始,所以就不難理解 func.length - 1,但是 +startIndex 又是為什么呢,答案是同樣是考慮數(shù)組排序是從 0 開始。其實在源碼中 restArgs 這個內(nèi)部函數(shù)作者還并沒有用到過 startIndex 這個參數(shù),如果需要使用那么它的意義在于 return function 的時候處理 function 中的一部分參數(shù),我們現(xiàn)在假設(shè)使用了 startIndex 參數(shù),如果 startIndex >2 即拋去 arguments[startIndex + 1] 作為傳入?yún)?shù)的一步限定,然后將 arguments[arguments.length - startIndex + 1] ~ arguments[arguments.length] 封裝數(shù)組作為 arguments[startIndex] 傳入,當(dāng)然這過程中需要將 arguments[arguments.length - startIndex + 1] ~ arguments[arguments.length] 從 arguments 刪除,所以源碼中運(yùn)用了多個 Array 用于這一過程其目的就是重組 arguments。而當(dāng) 0 時,同學(xué)們應(yīng)該很容易理解 switch (startIndex),這里就不再多說了。
前面說到作者并沒有使用 startIndex 這個參數(shù),那么沒有 startIndex 是什么情況呢,startIndex = func.length - 1 就是說設(shè)定 Array 的長度即 arguments 的長度,我們可以看到作者對 restArgs 這個函數(shù)很重視,并且好像一直在優(yōu)化它,作者想要做什么也不得而知,畢竟拋開 startIndex 的話:

  var restArgs = function(func) {
    startIndex = func.length - 1;
    return function() {
      var rest = Array(1);
      rest[0] = arguments[startIndex];
      var args = Array(arguments.length);
      for (index = 0; index < startIndex; index++) {
        args[index] = arguments[index];
      }
      args[startIndex] = rest;
      return func.apply(this, args);
    };
  };

等同于:

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

作者將5行代碼擴(kuò)展到21行,其實就是為了一個 startIndex 而已。

  var baseCreate = function(prototype) {
    if (!_.isObject(prototype)) return {};
    if (nativeCreate) return nativeCreate(prototype);
    Ctor.prototype = prototype;
    var result = new Ctor;
    Ctor.prototype = null;
    return result;
  };

baseCreate 用于創(chuàng)建一個干凈且只存在具有想要其具有 prototype 的函數(shù),第一個判斷是否具有 prototype 參數(shù),第二個判斷運(yùn)用 Object.create 創(chuàng)建,余下則是自己運(yùn)用 Ctor 這個空函數(shù)創(chuàng)建,沒什么可細(xì)說的。

  var property = function(key) {
    return function(obj) {
      return obj == null ? void 0 : obj[key];
    };
  };

property 用于獲取 obj 的 key 值,通過 property() 設(shè)置 key ,重點是設(shè)置兩個字,有 key 則以沒有則創(chuàng)建之。

  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;

設(shè)置 一個最大值 MAX_ARRAY_INDEX,Math.pow(2, 53) - 1 意為2的53次冪等于9007199254740991,Math 的相關(guān)函數(shù)參考 Math,其實我一直覺得 MAX_ARRAY_INDEX 并不用設(shè)置這么大的值,Math.pow(2, 16) 就足以。

  var getLength = property("length");

設(shè)置 obj 的 key 值并生成函數(shù),等同于:

  var getLength = function(obj) {
         return obj == null ? void 0 : obj["length"];
    };
  var isArrayLike = function(collection) {
    var length = getLength(collection);
    return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX;
  };

isArrayLike,使 Obj 具有 length 屬性且有值則返回 true,否則返回 false,這是一個判斷函數(shù)。

  _.each = _.forEach = function(obj, iteratee, context) {
    iteratee = optimizeCb(iteratee, context);
    var i, length;
    if (isArrayLike(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
        iteratee(obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };

我一直以為 JAVASCRIPT 最精華的就是回調(diào)的執(zhí)行方式,雖然互聯(lián)網(wǎng)上一些文章總在說回調(diào)毀了一切,人云亦云等等,但是回調(diào)支撐起了所有的框架,而且回調(diào)很優(yōu)雅用的好可以很舒服,回調(diào)不是毀了一切只是因為某些人不恰當(dāng)?shù)脑O(shè)置回調(diào)毀了他自己的代碼。在 _.forEach 中 iteratee 即回調(diào)函數(shù),其中運(yùn)用了 optimizeCb 優(yōu)化回調(diào),然后是一個常規(guī)判斷,這里為什么用 isArrayLike(obj) 而不是 isArray(obj) 來判斷是不是數(shù)組呢,留下一個思考問題。

  _.map = _.collect = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length,
        results = Array(length);
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      results[index] = iteratee(obj[currentKey], currentKey, obj);
    }
    return results;
  };

封裝 map 函數(shù),沒什么好說的,參考 Map、Map.prototype、WeakMap 用于知識儲備,至于作者的 _.map 更多的是根據(jù)一定的條件遍歷 obj 中的元素,與 _.forEach 的更大區(qū)別是 _.forEach 不會對傳入的 obj 做改動直接 return obj,而 _.mapreturn resultsreturn results 是每個 iteratee 回調(diào)的集合。

  var createReduce = function(dir) {
    var reducer = function(obj, iteratee, memo, initial) {
      var keys = !isArrayLike(obj) && _.keys(obj),
          length = (keys || obj).length,
          index = dir > 0 ? 0 : length - 1;
      if (!initial) {
        memo = obj[keys ? keys[index] : index];
        index += dir;
      }
      for (; index >= 0 && index < length; index += dir) {
        var currentKey = keys ? keys[index] : index;
        memo = iteratee(memo, obj[currentKey], currentKey, obj);
      }
      return memo;
    };
    return function(obj, iteratee, memo, context) {
      var initial = arguments.length >= 3;
      return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
    };
  };

createReduce,創(chuàng)建 reduce。關(guān)于 reduce 的介紹可見 reduce 方法 (Array) (JavaScript):https://msdn.microsoft.com/library/ff679975(v=vs.94).aspx 和 array-reduce,作者這里的 reduce 肯定不是這樣,但既然命名為 createReduce,想來也脫不了太多關(guān)系。函數(shù)中 reducer 首先定義 keys,其值為 obj 的 key 集合或者 false,后面幾個語句里都有對于 keys 的三元運(yùn)算,目的就是排除 obj 不為 Object 的可能性。接下來判斷傳入 initial,如果傳入 initial 為 false 則默認(rèn) memo 值為 keys[keys.length-1] || 0,之后是 for 循環(huán)遍歷回調(diào),并返回最后一個回調(diào)值。跳出 reducer 函數(shù) return function 的恰恰是引用 reducer 函數(shù)的外部接口,于是所有一切都連貫上了,包括 initial 的定義是 arguments 長度大于等于3等等。
我們再重新過一遍代碼,在最外部 return 的時候判斷 initial,實際上就是再確定是否傳入了 memo 和 context,當(dāng)然最主要的就是 memo,以此來確定在內(nèi)部 reducer 的時候是否具有初始值。在這里我覺得作者應(yīng)該對 memo 進(jìn)行類型判斷的,如果是 Number 或者 String 還說的過去,但是如果傳入 memo 是 Object 就有點說不過去了,會出錯的。比如:

    _.reduce([1, 2, 3], function(memo, num){ return memo + num; });
    6
    _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 1);
    7
    _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, "1");
    "1123"
    _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, []);
    "123"
    _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, [1,2]);
    "1,2123"
    _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, {a:1});
    "[object Object]123"
  _.reduce = _.foldl = _.inject = createReduce(1);

這里就是用 createReduce 包裝好的 _.reduce,不解釋。

  _.reduceRight = _.foldr = createReduce(-1);

這里就是用 createReduce 包裝好的 _.reduceRight,與 _.reduce 計算順序相反即從右面向左面開始。

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

    dack 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<