很早就想研究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
雖然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._ = _; }