underscore.js源碼研究(1)

概述

很早就想研究underscore源碼了,雖然underscore.js這個庫有些過期了,可是我仍是想學習一下庫的架構,函數式編程以及經常使用方法的編寫這些方面的內容,又剛好沒什麼其它要研究的了,因此就告終研究underscore源碼這一心願吧。html

underscore.js源碼研究(1)
underscore.js源碼研究(2)
underscore.js源碼研究(3)
underscore.js源碼研究(4)
underscore.js源碼研究(5)
underscore.js源碼研究(6)
underscore.js源碼研究(7)
underscore.js源碼研究(8)node

參考資料:underscore.js官方註釋undersercore 源碼分析undersercore 源碼分析 segmentfaultjquery

void 0

雖然window的全局屬性undefined是隻讀的,可是undefined能夠在函數做用域內被改寫。git

因此通常用void 0代替undefined,另外一方面也能夠減小字節。編程

緩存方法

一直以來,我覺得下面這段代碼的做用只是緩存方法而已:segmentfault

var ArrayProto = Array.prototype, 
    ObjProto = Object.prototype;

但是我錯了,這段代碼的真正意圖是便於壓縮。示例以下:api

ArrayProto.slice.call(arr, parameter);
//上述代碼通常被壓縮爲:
a.slice.call(arr, parameter);

//可是由於Array是關鍵字,下面的代碼不能被壓縮:
Array.prototype.slice.call(arr, parameter);

庫的對象

不少庫都會有本身的對象,好比jquery對象,underscore對象,初看起來很是神祕,但其實只是給它掛載了一些方法罷了。瀏覽器

//既起到了函數的做用,又起到了構造函數的做用
//當obj不是_的實例時,以obj爲參數新建一個實例(underscore對象)
var _ = function (obj) {
  if (obj instanceof _) return obj;
  if (!(this instanceof _)) return new _(obj);
  this._wrapped = obj;
};

利用上述代碼能夠用_([1, 2, 3])的形式把[1, 2, 3]變成一個underscore對象,並利用下面的代碼給這個對象添加方法:緩存

//混入
_.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
        //直接掛載,使之可以函數式調用
        var func = _[name] = obj[name];
        //掛載到prototype上,使之可以OOP調用
        _.prototype[name] = function() {
            var args = [this._wrapped];
            push.apply(args, arguments);
            return chainResult(this, func.apply(_, args));
      };
    });
    return _;
};

_.mixin(_);

須要注意的是,underscore的全部方法都是先直接掛載到_下面,而後經過_.mixin(_);語句一併掛載到_.prototype下面使之可以OOP調用的。服務器

值得一提的是,underscore也支持函數式編程範式:經過_.map()這樣的形式直接調用map等方法。

判斷瀏覽器仍是服務器

underscore.js既可用於瀏覽器還能夠用於服務器,它是用下面的代碼判斷瀏覽器和服務器的:

var root = typeof self == 'object' && self.self === self && self ||
            typeof global == 'object' && global.global === global && global ||
            this ||
            {};

而後用下面的代碼把_掛載到全局變量上面:

if (typeof exports != 'undefined' && !exports.nodeType) {
  if (typeof module != 'undefined' && !module.nodeType && module.exports) {
      exports = module.exports = _;
  }
  exports._ = _;
} else {
  root._ = _;
}
相關文章
相關標籤/搜索