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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...