成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JS基礎(chǔ)篇-underscore源碼解析

anyway / 2745人閱讀

摘要:總想找個機會夯實一下自己的基礎(chǔ),正好最近略有清閑,看視頻讀書擼代碼我選擇了第三者怎么感覺有點別扭,看視頻的話效率不高適合入門,看書的話一本你不知道的推薦給大家,選擇繼續(xù)看書的話還是算了吧,畢竟讀萬卷書不如行萬里路是吧。

總想找個機會夯實一下自己的JS基礎(chǔ),正好最近略有清閑,看視頻?讀書?擼代碼?我選擇了第三者(怎么感覺有點別扭),看視頻的話效率不高適合入門,看書的話,一本《你不知道的JavaScript》推薦給大家,選擇繼續(xù)看書的話還是算了吧,畢竟讀萬卷書不如行萬里路是吧。擼代碼的話,擼個項目?自己雜七雜八寫了不少了,都是老套路難有新的突破,想想倒不如研究研究大神的代碼,學(xué)習(xí)學(xué)習(xí)大神的結(jié)構(gòu)設(shè)計,技術(shù)細(xì)節(jié)等站在大神的肩膀上是吧。在選擇是翻譯Loadsh或Underscore的時候我更偏向于前者,因為念起來比較順嘴,但當(dāng)我看到Loadsh源碼的時候發(fā)現(xiàn),這個!這個!我發(fā)現(xiàn)“安得兒私購”其實也挺順嘴的,1600多行,API豐富,結(jié)構(gòu)清晰,就你了。最后在補充幾句,看源碼的感覺有點像“春天的雨,潤物細(xì)無聲”,沒感覺自己技術(shù)有多大提高,但當(dāng)看到其他類庫的時候已經(jīng)知其大概結(jié)構(gòu),當(dāng)要自己實現(xiàn)_.flatten或_.chain的時候已經(jīng)有了思路,也算是有所進(jìn)步吧。此分析文章會持續(xù)更新,如有錯誤感謝提出!
原文地址

//參考文檔:http://underscorejs.org/
//參考文檔:http://www.bootcss.com/p/underscore/
/*
  建議:
      1 剛開始不要一行一行跟下來敲,先了解一下庫的整體結(jié)構(gòu)
      2 遇到不懂的打個斷點,多跟蹤幾遍,斷點很重要
      3 有些內(nèi)部函數(shù)使用頻率很高(cb....),這些內(nèi)部函數(shù)了解清楚了后續(xù)看起來輕松不少
      4 有些函數(shù)內(nèi),有較多的函數(shù)引用,建議多讀幾遍

*/
(function() {
  //獲取根對象,瀏覽器是window(self),Node是global,window.window===window返回true,global亦然
  var root = typeof self == "object" && self.self === self && self ||
            typeof global == "object" && global.global === global && global ||
            this ||
            {};
  //獲取現(xiàn)有的_對象,避免沖突,具體解決沖突方法后面會說
  var previousUnderscore = root._;
  //獲取原型對象,為的是寫起來方便不用每次都xxx.proto...一大推
  var ArrayProto = Array.prototype, ObjProto = Object.prototype;
  var SymbolProto = typeof Symbol !== "undefined" ? Symbol.prototype : null;

  var push = ArrayProto.push,
      slice = ArrayProto.slice,
      toString = ObjProto.toString,
      hasOwnProperty = ObjProto.hasOwnProperty;

  var nativeIsArray = Array.isArray,
      nativeKeys = Object.keys,
      nativeCreate = Object.create;
  //中轉(zhuǎn)函數(shù),后面用到會說
  var Ctor = function(){};
  /*
  _的構(gòu)造函數(shù),
  第一步是看看obj是否是_的實例,如果是就不操作直接返回,有點像$($("#d1")),jq或zepto里也有相似的判斷
  第二步是判斷this是否是_的實例,不是則進(jìn)行new 調(diào)用,
  注意,在進(jìn)行new調(diào)用的時候 new會做4件事,1創(chuàng)建空對象,2空對象的__proto__指向函數(shù)的prototype,3this指向空對象(此時可能會添加屬性等),4判斷返回值,
  而此時在當(dāng)前的_里this已經(jīng)指向空對象
  第三步為當(dāng)前對象添加_wrapped屬性,這是為了后面的鏈?zhǔn)秸{(diào)用做準(zhǔn)備
  */
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };

  //根據(jù)當(dāng)前環(huán)境添加_對象
  if (typeof exports != "undefined" && !exports.nodeType) {
    if (typeof module != "undefined" && !module.nodeType && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  }
   else {
    root._ = _;
  }

  // 版本號
  _.VERSION = "1.8.3";

  //下面就是一些常用的方法了,后面會一點一點分析
  // _.each=_.forEach=function(){......}
  //...
  //...
  //...


  /*
  鏈?zhǔn)胶瘮?shù)
  實例化當(dāng)前對象,設(shè)置_china為true,此為判斷鏈?zhǔn)秸{(diào)用屬性,true為鏈?zhǔn)秸{(diào)用
  */
  _.chain = function(obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
  };

  //判斷是否繼續(xù)鏈?zhǔn)秸{(diào)用
  var chainResult = function(instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
  };

  /*
  擴(kuò)展_的方法 
  第一步遍歷obj里所含方法,執(zhí)行回調(diào)
  回調(diào)內(nèi)  
      1獲取obj的function,擴(kuò)展到_里,并保存到func
      2對_的prototype進(jìn)行擴(kuò)展,擴(kuò)展函數(shù)里進(jìn)行取值添加等操作(注意this指向),最后執(zhí)行func.apply(_, args)(注意apply還有打散數(shù)組的功能)把結(jié)果和this作為參數(shù)傳遞到chainResult中,判斷是否繼續(xù)鏈?zhǔn)秸{(diào)用
  第二步 返回_
  
  最后在解釋一下為什么_.prototype[name]=function(){....},如果理解請?zhí)^此段
  大家一般都是_.filter({name:"Mr.zhou"},function(){.....})
  鏈?zhǔn)秸{(diào)用說白了就是將第一個方法的執(zhí)行結(jié)果作為參數(shù)傳到第二個方法里,如此依次傳遞,直到最后一個返回結(jié)果;
  想要鏈?zhǔn)秸{(diào)用常用的_.filter(...)的方法肯定是不行了,具體實現(xiàn)請看例子
  var stooges = [{name: "curly", age: 25}, {name: "moe", age: 21}, {name: "larry", age: 23}];
  var youngest = _.chain(stooges)
                    .sortBy(function(stooge){ return stooge.age; })
                    .value();
  1 創(chuàng)建stooges對象
  2 創(chuàng)建youngest變量
  3 詳細(xì)看一下youngest值的計算方法
    3.1 先是_.chain(stooges)這句話做了什么呢?(可以回顧一下之前的代碼)
      調(diào)用_.chain(stooges),內(nèi)部對_進(jìn)行實例化,并把stooges作為_wrapped的值,并添加了一個名為_chain值為true的屬性,
      最后得到的就是這樣一個對象{_wrapped:[{name: "curly", age: 25}...],_chain:true}
    3.2 繼續(xù)調(diào)用
      {_wrapped:[{name: "curly", age: 25}...],_chain:true}.sortBy(function(stooge){ return stooge.age; })
                                                          .value();
      等等,這樣對嗎?內(nèi)個什么對象調(diào)用.sortBy不報錯嗎?它有這個方法嗎?
      是有的,你沒聽錯,那么在哪里呢?
      請看_.mixin的這句換_.prototype[name]=function(){....}
      這句話就是在往_的原型對象中添加方法,在這句話之前的_.mixin(_),與其內(nèi)部的_.each(_.function(obj),...)就是將_上面的所有方法的地址引用傳遞給_.prototype上,而{_wrapped:[{name: "curly", age: 25}...],_chain:true}對象又是_的實例對象,自然也就繼承了_.prototype的方法,這也就是鏈?zhǔn)秸{(diào)用的原理
    3.3 最后調(diào)用value()來返回它的_wrapped就此結(jié)束
    */
  _.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
      var func = _[name] = obj[name];
      _.prototype[name] = function() {
        var args = [this._wrapped];
        push.apply(args, arguments);
        return chainResult(this, func.apply(_, args));
      };
    });
    return _;
  };

  //自調(diào)mixin并把_傳入
  _.mixin(_);

  // 同mixin差不多添加方法
  _.each(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      var obj = this._wrapped;
      method.apply(obj, arguments);
      if ((name === "shift" || name === "splice") && obj.length === 0) delete obj[0];
      return chainResult(this, obj);
    };
  });

  // 同mixin差不多添加方法
  _.each(["concat", "join", "slice"], function(name) {
    var method = ArrayProto[name];
    _.prototype[name] = function() {
      return chainResult(this, method.apply(this._wrapped, arguments));
    };
  });

  // _.chain的value方法
  _.prototype.value = function() {
    return this._wrapped;
  };

  //添加相應(yīng)方法
  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
  //添加相應(yīng)方法
  _.prototype.toString = function() {
    return String(this._wrapped);
  };

  //對AMD的兼容
  if (typeof define == "function" && define.amd) {
    define("underscore", [], function() {
      return _;
    });
  }
}());

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

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

相關(guān)文章

  • 源碼解讀這半年

    摘要:作者韓子遲不知不覺間,源碼解讀系列進(jìn)入了真正的尾聲,也請允許我最后一次下項目的原始地址這半年以來,花費了大量的業(yè)余時間,共計寫了篇隨筆包括此文,也給的源碼加了差不多行注釋,對于當(dāng)初說的要做史上最詳細(xì)的源碼剖析,至此我也覺得問心無愧。 作者:韓子遲 What? 不知不覺間,「Underscore 源碼解讀系列」進(jìn)入了真正的尾聲,也請允許我最后一次 po 下項目的原始地址 https://...

    zzzmh 評論0 收藏0
  • javascript知識點

    摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會討論安全的類型檢測惰性載入函數(shù)凍結(jié)對象定時器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對寫代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...

    Karrdy 評論0 收藏0
  • 即將立秋的《課多周刊》(第2期)

    摘要:即將立秋的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。課多周刊機器人運營中心是如何玩轉(zhuǎn)起來的分享課多周刊是如何運營并堅持下來的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大...

    ruicbAndroid 評論0 收藏0
  • 即將立秋的《課多周刊》(第2期)

    摘要:即將立秋的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。課多周刊機器人運營中心是如何玩轉(zhuǎn)起來的分享課多周刊是如何運營并堅持下來的。 即將立秋的《課多周刊》(第2期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大...

    MRZYD 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<