underscore.js源碼解析

来源:http://www.cnblogs.com/WhiteBlade/archive/2016/02/24/5215434.html
-Advertisement-
Play Games

underscore.js解析


一直想針對一個框架的源碼好好的學習一下編程思想和技巧,提高一下自己的水平,但是看過一些框架的源碼,都感覺看的莫名其妙,看不太懂,最後找到這個underscore.js由於這個比較簡短,一千多行,而且讀起來容易一些,所以就決定是它了,那廢話不多說開始我們的源碼學習。

underscore.js源碼GitHub地址: https://github.com/jashkenas/underscore/blob/master/underscore.js
  本文解析的underscore.js版本是1.8.3  

結構解析

  我們先從整體的結構開始分析(其中加入了註釋加以解釋說明)  
  1 (function() {
  2   // 創建一個root對象,在瀏覽器中表示為window(self)對象,在Node.js中表示global對象,
  3   // 之所以用用self代替window是為了支持Web Worker
  4   var root = typeof self == 'object' && self.self === self && self ||
  5             typeof global == 'object' && global.global === global && global ||
  6             this;
  7   // 保存"_"(下劃線變數)被覆蓋之前的值
  8   var previousUnderscore = root._;
  9   // 原型賦值,便於壓縮
 10   var ArrayProto = Array.prototype, ObjProto = Object.prototype;
 11   // 將內置對象原型中的常用方法賦值給引用變數,以便更方便的引用
 12   var push = ArrayProto.push,
 13       slice = ArrayProto.slice,
 14       toString = ObjProto.toString,
 15       hasOwnProperty = ObjProto.hasOwnProperty;
 16   // 定義了一些ECMAScript 5方法
 17   var nativeIsArray = Array.isArray,
 18       nativeKeys = Object.keys,
 19       nativeCreate = Object.create;
 20   //跟神馬裸函數有關,我也不清楚什麼意思,有知道可以告訴我
 21   var Ctor = function(){};
 22   // 創建一個下劃線對象
 23   var _ = function(obj) {
 24     // 如果在"_"的原型鏈上(即_的prototype所指向的對象是否跟obj是同一個對象,要滿足"==="的關係)
 25     if (obj instanceof _) return obj;
 26     // 如果不是,則構造一個
 27     if (!(this instanceof _)) return new _(obj);
 28     // 將underscore對象存放在_.wrapped屬性中
 29     this._wrapped = obj;
 30   };
 31   // 針對不同的宿主環境, 將Undersocre的命名變數存放到不同的對象中
 32   if (typeof exports != 'undefined' && !exports.nodeType) {//Node.js
 33     if (typeof module != 'undefined' && !module.nodeType && module.exports) {
 34       exports = module.exports = _;
 35     }
 36     exports._ = _;
 37   } else {//瀏覽器
 38     root._ = _;
 39   }
 40   //版本號
 41   _.VERSION = '1.8.3';
 42   //下麵是各種方法以後的文章中會具體說明
 43   .
 44   .
 45   .
 46   .
 47   .
 48   .
 49   // 創建一個chain函數,用來支持鏈式調用
 50   _.chain = function(obj) {
 51     var instance = _(obj);
 52     //是否使用鏈式操作
 53     instance._chain = true;
 54     return instance;
 55   };
 56   // 返回_.chain里是否調用的結果, 如果為true, 則返回一個被包裝的Underscore對象, 否則返回對象本身
 57   var chainResult = function(instance, obj) {
 58     return instance._chain ? _(obj).chain() : obj;
 59   };
 60   // 用於擴展underscore自身的介面函數
 61   _.mixin = function(obj) {
 62     //通過迴圈遍歷對象來淺拷貝對象屬性
 63     _.each(_.functions(obj), function(name) {
 64       var func = _[name] = obj[name];
 65       _.prototype[name] = function() {
 66         var args = [this._wrapped];
 67         push.apply(args, arguments);
 68         return chainResult(this, func.apply(_, args));
 69       };
 70     });
 71   };
 72   _.mixin(_);
 73   // 將Array.prototype中的相關方法添加到Underscore對象中, 這樣Underscore對象也可以直接調用Array.prototype中的方法
 74   _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
 75     //方法引用
 76     var method = ArrayProto[name];
 77     _.prototype[name] = function() {
 78       // 賦給obj引用變數方便調用
 79       var obj = this._wrapped;
 80       // 調用Array對應的方法
 81       method.apply(obj, arguments);
 82       if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
 83       //支持鏈式操作
 84       return chainResult(this, obj);
 85     };
 86   });
 87 
 88   // 同上,並且支持鏈式操作
 89   _.each(['concat', 'join', 'slice'], function(name) {
 90     var method = ArrayProto[name];
 91     _.prototype[name] = function() {
 92       //返回Array對象或者封裝後的Array
 93       return chainResult(this, method.apply(this._wrapped, arguments));
 94     };
 95   });
 96   //返回存放在_wrapped屬性中的underscore對象
 97   _.prototype.value = function() {
 98     return this._wrapped;
 99   };
100 
101   // 提供一些方法方便其他情況使用
102   _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
103   _.prototype.toString = function() {
104     return '' + this._wrapped;
105   };
106 
107   // 對AMD支持的一些處理
108   if (typeof define == 'function' && define.amd) {
109     define('underscore', [], function() {
110       return _;
111     });
112   }
113 }());

總結

具體分析在上面源碼中的註釋里寫的已經很詳細了,下麵再從頭理順一下整體的結構:   首先underscore包裹在一個匿名自執行的函數當中 內部定義了一個"_"變數 將underscore中的相關方法添加到_原型中,創建的_對象就具備了underscore方法 將Array.prototype中的相關方法添加到Underscore對象中, 這樣Underscore對象也可以直接調用Array.prototype中的方法

之後的文章中,我會針對underscore中的方法進行具體解析,感謝大家的觀看,也希望能夠和大家互相交流學習,有什麼分析的不對的地方歡迎大家批評指出

參考資料

https://segmentfault.com/a/1190000000515420
http://yalishizhude.github.io/2015/09/22/underscore-source/

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • userService 用戶 會員 系統設計 v2 q224 .doc 1. Admin login1 2. 普通用戶註冊登錄2 2.1. <!-- 會員退出登錄 -->2 2.2. <!-- 進入會員首頁 -->3 2.3. <!-- 進入會員信息 -->3 2.4. <!-- 修改會員密碼 --
  • javascript獲取隨機數很簡單,直接使用Math.random()即可,但這個函數只是獲取大於等於0小於1的隨機數,如果我們要獲取指定範圍內的隨機數,該如何實現呢?比如獲取5到50之間的隨機整數。本文章向大家介紹JavaScript 獲取指定範圍內的隨機整數,需要的碼農可以參考一下。 實現一個
  • 九宮格小游戲,可從本地圖庫載入一張圖片,填充到9個ImageView,另涉及Timer計時、圖庫控制項。每個格子都是相同的控制項,動態添加到首頁中的,在初始化後,響應touch事件,之後通過多次消息傳遞,來完成整個拼圖過程。裡面有個隨機發牌的經典演算法,也可參考。初始化時,激發每個格子的init事件和in
  • 1 $.ajax({ 2 type: "GET", 3 url: "handleAjaxRequest.action", 4 data: {paramKey:paramValue}, 5 async: true, 6 dataType:"json", 7 success: function(retu
  • 最近一直在惡補基礎JS H5 CSS3的基礎知識 關於這個瀑布流: 本來打算看著教程來做的。 不過 感覺理解起來有點複雜。 SO, 自己參考教程默寫了一個。。 目前我所接觸過的瀑布流佈局分為2大類 主要區分在於 float佈局 或者position佈局 點擊這裡下載Demo 貼下源碼:(可能有些BU
  • 基礎數據結構與演算法 現在有兩個不同的JSON,比較複雜,可以參考這裡的DEMO中返回的JSON。要比較它們的差異,除了用現成的工具如beyond compare以外,如果我們的機器上沒有安裝這個工具,能如何較快解決?作為一個程式員,一個個對比是不可行的,對比完也不會有什麼收穫。我會把之放進Excel
  • 21世紀,瀏覽器雜七雜八,足以讓你眼花繚亂。我們在做頁面相容性測試的時候,面對眾多的瀏覽器該如何調試我們的web頁面?其實,如果你瞭解了瀏覽器的內核,那麼就不會覺得頭疼。因為它們的內核並不是和他的數量一樣那麼多,常見的幾類內核可以歸為:Trident、Gecko、WebKit、Presto 四種。
  • 效果展示: html: <div class="sidebar"> <ul> <li>優先順序 <ul> <li><aonclick=""class="sidebar-selected">全部</a></li> <li><aonclick="">P1</a></li> <li><aonclick=""
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...