// ================當即執行函數================ // 使用(function(){}())當即執行函數,減小全局變量 // ----????----函數聲明 function (){} 與函數表達式 var funName = function(){}----????---- // function(){}() 結果會返回Uncaught SyntaxError: Unexpected token ( // 由於此處,編譯器會將function當作函數聲明關鍵字去編譯,而(並不能夠當作函數名 // (function(){}()) 能夠正常執行 // 此處function 被擋住表達式編譯 // ----????----函數聲明 function (){} 與函數表達式 var funName = function(){}----????---- // ~function(){}()/+function(){}()/-function(){}()/!function(){}() // true && function(){}() // 0,function(){} // 以上三種狀況下,function都會被當成表達式去編譯。 // 因此常常會在一個源碼中看到~function寫法吧// // ================當即執行函數================ (function(){}( // 建立root變量,保存全局根變量。 // 瀏覽器window // 服務器global,部分虛擬機this // WebWorker中爲self // ================&& ||操做================ // 邏輯與&& 的優先級高於 邏輯非|| // 邏輯與&&爲斷路邏輯, // 任何一個值var Boolean(var)==false,當即返回var,不然返回最後一個值 // 邏輯非||爲短路邏輯, // 任何一個值var Boolean(var)===true,當即返回var,,不然返回最後一個值 // ================&& ||操做================ var root = typeof self == 'object' && self.self === self && self || typeof global == 'object' && global.global === global && global || this || {}; // 保存已存在的全局中_變量,以便避免變量衝突 var previousUnderscore = root._; // Naked function reference for surrogate-prototype-swapping. // https://stackoverflow.com/questions/30496650/what-is-surrogate-prototype-swapping-in-javascript // 關於surrogate-prototype-swapping是什麼的理解: // Ctor就是一個裸函數,自己並無什麼特別的,特別之處在於用途 // Ctor用於在baseCreate函數中暫存要繼承的原型對象,並構造一個新的對象 var Ctor = function() {}; var nativeCreate = Object.create; // An internal function for creating a new object that inherits from another. // 內部函數,用於構造繼承指定對象prototype的新對象 var baseCreate = function(prototype) { if (!_.isObject(prototype)) return {}; if (nativeCreate) return nativeCreate(prototype); //暫存 Ctor.prototype = prototype; var result = new Ctor; //銷燬 Ctor.prototype = null; return result; }; // Create a safe reference to the Underscore object for use below. // 建立安全做用域 var _ = function(obj) { //obj在_原型鏈上 if (obj instanceof _) return obj; //不是,構造一個 if (!(this instanceof _)) return new _(obj); //將underscore對象存在_.wrapped屬性上 this._wrapped = obj; }; // Utility Functions // ----------------- // 避免衝突,將本來的_變量從新複製給_ _.noConflict = function() { root._ = previousUnderscore; return this; }; // Export the Underscore object for **Node.js**, with // backwards-compatibility for their old module API. If we're in // the browser, add `_` as a global object. // 在nodejs中導出,兼容舊版本 // nodeTyoe用於檢測變量是否爲HTML元素 // (`nodeType` is checked to ensure that `module` // and `exports` are not HTML elements.) if (typeof exports != 'undefined' && !exports.nodeType) { if (typeof module != 'undefined' && !module.nodeType && module.exports) { exports = module.exports = _; } exports._ = _; } else { root._ = _; } // AMD registration happens at the end for compatibility with AMD loaders // that may not enforce next-turn semantics on modules. Even though general // practice for AMD registration is to be anonymous, underscore registers // as a named module because, like jQuery, it is a base library that is // popular enough to be bundled in a third party lib, but not be part of // an AMD load request. Those cases could generate an error when an // anonymous define() is called outside of a loader request. // AMD規範導出 if (typeof define == 'function' && define.amd) { define('underscore', [], function() { return _; }); } ))