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

資訊專欄INFORMATION COLUMN

Underscore源碼解析(一)

neu / 2556人閱讀

摘要:本文同步自我得博客最近準(zhǔn)備折騰一下,在事先了解了之后,我知道了對(duì)這個(gè)庫(kù)有著強(qiáng)依賴,正好之前也沒使用過,于是我就想先把徹底了解一下,這樣之后折騰的時(shí)候也少一點(diǎn)阻礙。

本文同步自我得博客:http://www.joeray61.com

最近準(zhǔn)備折騰一下backbone.js,在事先了解了backbone之后,我知道了backbone對(duì)underscore這個(gè)庫(kù)有著強(qiáng)依賴,正好underscore之前也沒使用過,于是我就想先把underscore徹底了解一下,這樣之后折騰backbone的時(shí)候也少一點(diǎn)阻礙。

*underscore*是一個(gè)很實(shí)用且小巧的框架,提供了很多我們?cè)诰幊虝r(shí)需要的基本功能函數(shù),而且他沒有擴(kuò)展*javascript*的原生對(duì)象,主要涉及對(duì)*Object*、*Array*、*Function*的操作。
我曾經(jīng)問我的朋友[@小胡子哥][1] 怎么學(xué)習(xí)一個(gè)框架?他給我的回答是:“直接看源碼。”現(xiàn)在想想深感同意,因?yàn)檠芯吭创a是最直接的學(xué)習(xí)途徑,可以深入地了解這個(gè)框架的思想和精髓,同時(shí)也能學(xué)習(xí)框架作者的編程技巧,提升自己的coding水平。
好了,題外話就說到這里,下面咱們進(jìn)入正題。
簡(jiǎn)化源碼看結(jié)構(gòu)

我這次看的underscore版本是1.3.3,整個(gè)文件也就1000多行,我把代碼簡(jiǎn)化了一下,并加入了相關(guān)的注釋:

// underscore的代碼包裹在一個(gè)匿名自執(zhí)行函數(shù)中
(function() {
    // 創(chuàng)建一個(gè)全局對(duì)象, 在瀏覽器中表示為window對(duì)象, 在Node.js中表示global對(duì)象
     var root = this;

     // 保存"_"(下劃線變量)被覆蓋之前的值
     // 如果出現(xiàn)命名沖突或考慮到規(guī)范, 可通過_.noConflict()方法恢復(fù)"_"被Underscore占用之前的值, 并返回Underscore對(duì)象以便重新命名
     var previousUnderscore = root._;

     // 創(chuàng)建一個(gè)空的對(duì)象常量, 便于內(nèi)部共享使用
     var breaker = {};

     // 將內(nèi)置對(duì)象的原型鏈緩存在局部變量
     var ArrayProto = Array.prototype, 
     ObjProto = Object.prototype, 
     FuncProto = Function.prototype;

     // 將內(nèi)置對(duì)象原型中的常用方法緩存在局部變量
     var slice = ArrayProto.slice, 
     unshift = ArrayProto.unshift, 
     toString = ObjProto.toString,
     hasOwnProperty = ObjProto.hasOwnProperty;

     // 這里定義了一些JavaScript 1.6提供的新方法
     // 如果宿主環(huán)境中支持這些方法則優(yōu)先調(diào)用, 如果宿主環(huán)境中沒有提供, 則會(huì)由Underscore實(shí)現(xiàn)
     var nativeForEach = ArrayProto.forEach, 
     nativeMap = ArrayProto.map, 
     nativeReduce = ArrayProto.reduce, 
     nativeReduceRight = ArrayProto.reduceRight, 
     nativeFilter = ArrayProto.filter, 
     nativeEvery = ArrayProto.every, 
     nativeSome = ArrayProto.some, 
     nativeIndexOf = ArrayProto.indexOf, 
     nativeLastIndexOf = ArrayProto.lastIndexOf, 
     nativeIsArray = Array.isArray, 
     nativeKeys = Object.keys, 
     nativeBind = FuncProto.bind;

     // 創(chuàng)建對(duì)象式的調(diào)用方式, 將返回一個(gè)Underscore包裝器, 包裝器對(duì)象的原型中包含Underscore所有方法(類似與將DOM對(duì)象包裝為一個(gè)jQuery對(duì)象)
     var _ = function(obj) {
         // 所有Underscore對(duì)象在內(nèi)部均通過wrapper對(duì)象進(jìn)行構(gòu)造
         return new wrapper(obj);
     };

     // 針對(duì)不同的宿主環(huán)境, 將Undersocre的命名變量存放到不同的對(duì)象中
     if( typeof exports !== "undefined") {// Node.js環(huán)境
         if( typeof module !== "undefined" && module.exports) {
             exports = module.exports = _;
         }
         exports._ = _;
     } else {// 瀏覽器環(huán)境中Underscore的命名變量被掛在window對(duì)象中
         root["_"] = _;
     }

     // 版本聲明
     _.VERSION = "1.3.3";

    //在_對(duì)象上定義各種方法
    . . . . . .

     // underscore對(duì)象的包裝函數(shù)
     var wrapper = function(obj) {
         // 原始數(shù)據(jù)存放在包裝對(duì)象的_wrapped屬性中
         this._wrapped = obj;
     };

     // 將Underscore的原型對(duì)象指向wrapper的原型, 因此通過像wrapper原型中添加方法, Underscore對(duì)象也會(huì)具備同樣的方法
     _.prototype = wrapper.prototype;

     // 返回一個(gè)對(duì)象, 如果當(dāng)前Underscore調(diào)用了chain()方法(即_chain屬性為true), 則返回一個(gè)被包裝的Underscore對(duì)象, 否則返回對(duì)象本身
    // result函數(shù)用于在構(gòu)造方法鏈時(shí)返回Underscore的包裝對(duì)象
     var result = function(obj, chain) {
         return chain ? _(obj).chain() : obj;
     };

     // 將一個(gè)自定義方法添加到Underscore對(duì)象中(實(shí)際是添加到wrapper的原型中, 而Underscore對(duì)象的原型指向了wrapper的原型)
     var addToWrapper = function(name, func) {
         // 向wrapper原型中添加一個(gè)name函數(shù), 該函數(shù)調(diào)用func函數(shù), 并支持了方法鏈的處理
         wrapper.prototype[name] = function() {
             // 獲取func函數(shù)的參數(shù), 并將當(dāng)前的原始數(shù)據(jù)添加到第一個(gè)參數(shù)
             var args = slice.call(arguments);
             unshift.call(args, this._wrapped);
             // 執(zhí)行函數(shù)并返回結(jié)果, 并通過result函數(shù)對(duì)方法鏈進(jìn)行封裝, 如果當(dāng)前調(diào)用了chain()方法, 則返回封裝后的Underscore對(duì)象, 否則返回對(duì)象本身
             return result(func.apply(_, args), this._chain);
         };
     };

     // 將內(nèi)部定義的_(即Underscore方法集合對(duì)象)中的方法復(fù)制到wrapper的原型鏈中(即Underscore的原型鏈中)
     // 這是為了在構(gòu)造對(duì)象式調(diào)用的Underscore對(duì)象時(shí), 這些對(duì)象也會(huì)具有內(nèi)部定義的Underscore方法
     _.mixin(_);

     // 將Array.prototype中的相關(guān)方法添加到Underscore對(duì)象中, 因此在封裝后的Underscore對(duì)象中也可以直接調(diào)用Array.prototype中的方法
     // 如: _([]).push()
     each(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function(name) {
         // 獲取Array.prototype中對(duì)應(yīng)方法的引用
         var method = ArrayProto[name];
         // 將該方法添加到Underscore對(duì)象中(實(shí)際是添加到wrapper的原型對(duì)象, 因此在創(chuàng)建Underscore對(duì)象時(shí)同時(shí)具備了該方法)
         wrapper.prototype[name] = function() {
             // _wrapped變量中存儲(chǔ)Underscore對(duì)象的原始值
             var wrapped = this._wrapped;
            // 調(diào)用Array對(duì)應(yīng)的方法并返回結(jié)果
             method.apply(wrapped, arguments);
             var length = wrapped.length;
             if((name == "shift" || name == "splice") && length === 0)
                 delete wrapped[0];
             // 即使是對(duì)于Array中的方法, Underscore同樣支持方法鏈操作
             return result(wrapped, this._chain);
         };
     });

     // 作用同于上一段代碼, 將數(shù)組中的一些方法添加到Underscore對(duì)象, 并支持了方法鏈操作
     // 區(qū)別在于上一段代碼所添加的函數(shù), 均返回Array對(duì)象本身(也可能是封裝后的Array), concat, join, slice方法將返回一個(gè)新的Array對(duì)象(也可能是封裝后的Array)
     each(["concat", "join", "slice"], function(name) {
         var method = ArrayProto[name];
         wrapper.prototype[name] = function() {
             return result(method.apply(this._wrapped, arguments), this._chain);
         };
     });

     // 對(duì)Underscore對(duì)象進(jìn)行鏈?zhǔn)讲僮鞯穆暶鞣椒?     wrapper.prototype.chain = function() {
         // this._chain用來標(biāo)示當(dāng)前對(duì)象是否使用鏈?zhǔn)讲僮?         // 對(duì)于支持方法鏈操作的數(shù)據(jù), 一般在具體方法中會(huì)返回一個(gè)Underscore對(duì)象, 并將原始值存放在_wrapped屬性中, 也可以通過value()方法獲取原始值
         this._chain = true;
         return this;
     };

     // 返回被封裝的Underscore對(duì)象的原始值(存放在_wrapped屬性中)
     wrapper.prototype.value = function() {
         return this._wrapped;
    };

}).call(this);
小結(jié)

underscore這個(gè)庫(kù)的結(jié)構(gòu)(或者說思路)大致是這樣的:

    創(chuàng)建一個(gè)包裝器, 將一些原始數(shù)據(jù)進(jìn)行包裝,所有的*undersocre*對(duì)象, 內(nèi)部均通過*wrapper*函數(shù)進(jìn)行構(gòu)造和封裝
    *underscore*與*wrapper*的內(nèi)部關(guān)系是:

內(nèi)部定義變量_, 將underscore相關(guān)的方法添加到_, 這樣就可以支持函數(shù)式的調(diào)用, 如_.bind()

內(nèi)部定義wrapper類, 將_的原型對(duì)象指向wrapper類的原型

underscore相關(guān)的方法添加到wrapper原型, 創(chuàng)建的_對(duì)象就具備了underscore的方法

Array.prototype相關(guān)方法添加到wrapper原型, 創(chuàng)建的_對(duì)象就具備了Array.prototype中的方法

new _()時(shí)實(shí)際創(chuàng)建并返回了一個(gè)wrapper()對(duì)象, 并將原始數(shù)組存儲(chǔ)到_wrapped變量, 并將原始值作為第一個(gè)參數(shù)調(diào)用對(duì)應(yīng)方法

之后我會(huì)對(duì)underscore中所有方法的具體實(shí)現(xiàn)進(jìn)行介紹,感謝關(guān)注 

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

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

相關(guān)文章

  • Underscore源碼解析(四)

    摘要:本文同步自我得博客我在這個(gè)系列的第一篇文章說過,我學(xué)是為了在學(xué)的時(shí)候少一些阻礙,從第一篇的寫作時(shí)間到今天,大概也有個(gè)十幾二十天,感覺拖得有點(diǎn)久,所以今天將會(huì)是源碼解析系列的最后一篇文章,我會(huì)在這篇文章中介紹剩下的所有函數(shù)。 本文同步自我得博客:http://www.joeray61.com 我在這個(gè)系列的第一篇文章說過,我學(xué)underscore是為了在學(xué)backbone的時(shí)候少一些阻礙...

    高勝山 評(píng)論0 收藏0
  • Underscore源碼解析(二)

    摘要:本文同步自我得博客最近十幾天都在忙畢業(yè)論文的事,所以上一次為大家介紹完這個(gè)框架的結(jié)構(gòu)或者說是這個(gè)框架的設(shè)計(jì)思路之后就一直沒動(dòng)靜了,今天我又滿血復(fù)活了,讓我們繼續(xù)來探索的源碼奧秘吧。 本文同步自我得博客:http://www.joeray61.com 最近十幾天都在忙畢業(yè)論文的事,所以上一次為大家介紹完underscore這個(gè)框架的結(jié)構(gòu)(或者說是這個(gè)框架的設(shè)計(jì)思路)之后就一直沒動(dòng)靜了,今...

    騫諱護(hù) 評(píng)論0 收藏0
  • JS基礎(chǔ)篇-underscore源碼解析

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

    anyway 評(píng)論0 收藏0
  • Underscore源碼中文注釋(轉(zhuǎn))

    摘要:創(chuàng)建一個(gè)全局對(duì)象在瀏覽器中表示為對(duì)象在中表示對(duì)象保存下劃線變量被覆蓋之前的值如果出現(xiàn)命名沖突或考慮到規(guī)范可通過方法恢復(fù)被占用之前的值并返回對(duì)象以便重新命名創(chuàng)建一個(gè)空的對(duì)象常量便于內(nèi)部共享使用將內(nèi)置對(duì)象的原型鏈緩存在局部變量方便快速調(diào)用將 // Underscore.js 1.3.3 // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc....

    Guakin_Huang 評(píng)論0 收藏0
  • underscore源碼解析

    說明1、源碼結(jié)構(gòu)通覽,簡(jiǎn)單注釋說明2、通過調(diào)用方法講解核心代碼邏輯 一、源碼的結(jié)構(gòu) 為了方便比對(duì)源碼,按源碼的結(jié)構(gòu)順序展示。underscore是個(gè)輕量級(jí)的工具庫(kù),大部分代碼是實(shí)現(xiàn)特定功能以函數(shù)的形式存在,本身會(huì)比較簡(jiǎn)單,沒對(duì)方法具體說明,可直接參考underscore中文文檔 (function() { var root = this; var previousUnderscore = ...

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

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

0條評(píng)論

neu

|高級(jí)講師

TA的文章

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