1. 程式人生 > >backbone原始碼學習中的知識點整理(一)

backbone原始碼學習中的知識點整理(一)

一、self

var root = (typeof self == 'object' && self.self === self && self) || (typeof global == 'object' && global.global === global && global);

現代web之前的window.self和self

對於web頁面,在預設狀況下,下面4個寫法都是等同的:

window === self // true window.window === window.self // true window.self === self // true window.window === self // true

其實真實情況還就是這樣,並沒有需要self出場的理由,唯一可能有作用的就是更語義地判斷當前頁面是否作為iframe嵌入了,直接:

parent === self // true表示作為iframe嵌入,false則表示被iframe嵌入了

在HTML5一些新特性出來之前,全域性的self就是個沒什麼實用價值的半吊子。但是,隨著HTML5一些新特性的到來,self開始慢慢登上正式的舞臺,最常見的就是用在Service Workers或者Web Workers中。

無論是出來有段時間的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) { // ... });

二、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 並強制載入依賴模組。

三、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模組的特點如下:

1、所有程式碼都執行在模組作用域,不會汙染全域性作用域。

2、模組可以多次載入,但是隻會在第一次載入時執行一次,然後執行結果就被快取了,以後再載入,就直接讀取快取結果。要想讓模組再次執行,必須清除快取。

3、模組載入的順序,按照其在程式碼中出現的順序。

為了方便,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(); }; 
});