1、selfjavascript
var root = (typeof self == 'object' && self.self === self && self) || (typeof global == 'object' && global.global === global && global);
現代web以前的window.self和selfjava
對於web頁面,在默認情況下,下面4個寫法都是等同的:node
window === self // true window.window === window.self // true window.self === self // true window.window === self // true
其實真實狀況還就是這樣,並無須要self出場的理由,惟一可能有做用的就是更語義地判斷當前頁面是否做爲iframe嵌入了,直接:jquery
parent === self // true表示做爲iframe嵌入,false則表示被iframe嵌入了
在HTML5一些新特性出來以前,全局的self就是個沒什麼實用價值的半吊子。可是,隨着HTML5一些新特性的到來,self開始慢慢登上正式的舞臺,最多見的就是用在Service Workers或者Web Workers中。web
不管是出來有段時間的Web Workers或者說是新晉寵兒Service Workers,本質上都是開啓了另外的線程。編程
Workers開闢的新線程是沒有「窗體」這個概念的,都是在瀏覽器背後悄悄運行的線程,沒有窗體的概念也就意味着沒有window對象。換句話說,Service Workers和Web Workers相關的腳本中是不能使用window這個對象的。那問題來了,咱們但願在全局做用域裏面作事情該怎麼辦呢?數組
咱們可使用self來表示全局做用域,注意,只能是光禿禿的self,window.self這樣的寫法是不行的。瀏覽器
舉個簡單的例子,假設咱們註冊一個Service Workers,Workers腳本在sw-test.js中,以下:緩存
navigator.serviceWorker.register('/sw-test.js');
則咱們但願Service Workers註冊完畢乾點什麼事情,就能夠在sw-test.js中這麼寫:服務器
self.addEventListener('install', function(event) { // ... });
2、AMD
define(['underscore', 'jquery', 'exports'], function(_, $, exports) { //AMD的具體寫法,這裏不過多講述 root.Backbone = factory(root, exports, _, $); });
AMD,全稱 Asynchronous Module Definition,即異步模塊加載機制。AMD 規範很是簡單隻有一個API,即 define 函數:
define([module-name?],[array-of-dependencies?],[module-factory-or-object]);
其中,
module-name:模塊標識,能夠省略
array-of-dependencies:所依賴的模塊數組,能夠省略
module-factory-or-object:模塊的實現或者一個 JavaScript 對象
define 函數具備異步性,其首先會異步加載第二個參數中列出的依賴模塊,當全部的模塊被加載後,執行第三個參數的回調函數。
1)三個參數
define("A", ["require", "exports"], function(require, exports){ export.fun = function(){ return require("B").fun; } });
上述代碼定義了一個 A 模塊,而且依賴於內置的 require,exports 模塊,第三個參數是回調函數,能夠直接使用依賴的模塊,他們按依賴聲明順序做爲參數提供給回調函數。
require 函數是用來模塊依賴,即獲取模塊的引用,即便模塊沒有做爲參數定義,也可以被使用;
exports 定義 A 模塊實體,在其上定義的任何屬性和方法就是 A 模塊的屬性和方法。經過 exports.fun= … 就是爲 A 模塊定義了一個 fun 方法。
2)兩個參數
define 函數容許省略第一個參數,所以定義一個匿名模塊。這時候模塊文件的文件名就是模塊標識,即若是這個模塊文件名爲 A.js ,那麼 A 就是模塊名。能夠在依賴項目中用 A 來依賴於這個匿名模塊。這將帶來一個好處,就是模塊的高度可重用的。你拿來一個匿名模塊,隨便放在一個位置就可使用它,模塊名就是它的文件路徑。這也很好的符合了 DRY(Don’t Repeat Yourself)原則。
define(['A'], function(A){ return { fun: function(){ return A.fun() + 2; } }; });
3)一個參數
define 的前面兩個參數均可以省略;第三個參數有兩種狀況:一鍾是 JavaScript 對象,另外一種是一個函數。
若是是對象,能夠是包含方法的對象或者是隻提供數據。後者和 JSONP很是相似,所以,AMD能夠認爲包含了一個完整的JSONP實現。模塊演變爲一個簡單的數據對象,這樣的數據對象是高度可用的,並且由於是靜態對象,它也是CDN友好的,能夠提升JSONP的性能。
若是是函數,其用途之一是快速開發實現。適用於較小型的應用,該方式無需提早考慮須要引入的模塊,只需使用時,require 便可。
define(function(){ var a = require("A"); })
define函數在執行的時候,會調用函數的 toString 方法,並掃描其中的 require 調用,提早載入這些模塊,載入完成後再執行。
注意:Opera 不能很好的支持函數的 toString 方法,所以,在瀏覽器中它的適用性並不強。可是使用構建工具打包時,構建工具會掃描 require 並強制載入依賴模塊。
3、commonJs
//nodejs或者CommonJS的加載規範,這裏jQuery須要看成一個模塊來加載
} else if (typeof exports !== 'undefined') { var _ = require('underscore'), $; try { $ = require('jquery'); } catch (e) {} factory(root, exports, _, $); }
Node 應用由模塊組成,採用 CommonJS 模塊規範。每一個文件就是一個模塊,有本身的做用域。在一個文件裏面定義的變量、函數、類,都是私有的,對其餘文件不可見。
CommonJS規範規定,每一個模塊內部,module變量表明當前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,實際上是加載該模塊的module.exports屬性。
var x = 5; var addX = function (value) { return value + x; }; module.exports.x = x; module.exports.addX = addX;
require方法用於加載模塊。
CommonJS模塊的特色以下:
一、全部代碼都運行在模塊做用域,不會污染全局做用域。
二、模塊能夠屢次加載,可是隻會在第一次加載時運行一次,而後運行結果就被緩存了,之後再加載,就直接讀取緩存結果。要想讓模塊再次運行,必須清除緩存。
三、模塊加載的順序,按照其在代碼中出現的順序。
爲了方便,Node爲每一個模塊提供一個exports變量,指向module.exports。這等同在每一個模塊頭部,有一行這樣的命令。
若是你以爲,exports與module.exports之間的區別很難分清,一個簡單的處理方法,就是放棄使用exports,只使用module.exports。
CommonJS規範加載模塊是同步的,也就是說,只有加載完成,才能執行後面的操做。
AMD規範則是非同步加載模塊,容許指定回調函數。因爲Node.js主要用於服務器編程,模塊文件通常都已經存在於本地硬盤,因此加載起來比較快,不用考慮非同步加載的方式,因此CommonJS規範比較適用。可是,若是是瀏覽器環境,要從服務器端加載模塊,這時就必須採用非同步模式,所以瀏覽器端通常採用AMD規範。
AMD規範容許輸出的模塊兼容CommonJS規範
define(function (require, exports, module){ var someModule = require("someModule"); var anotherModule = require("anotherModule"); someModule.doTehAwesome(); anotherModule.doMoarAwesome(); exports.asplode = function (){ someModule.doTehAwesome(); anotherModule.doMoarAwesome(); }; });