模塊化
seajs
--CMD(就近依賴,只有用到纔會導出,瀏覽器端)requirejs
--AMD(前置依賴,瀏覽器端)commonJS
--node(服務器端)
commonjs
node自帶模塊化功能,一個js文件就是一個模塊,模塊this不是global,實現基礎是閉包。
模塊引用時會找到絕對路徑
模塊加載過會有緩存,把文件名作爲key,module作爲value
node實現模塊化就是增加了一個閉包,並且自執行這個閉包
模塊加載時是同步操作
默認會加後綴js,json,node
不同模塊下的變量不會相互衝突
//全局對象,在任意的地方都可以使用,不經過任何聲明就可以使用
//瀏覽器(在瀏覽器裏面,全局對象global是一個概念,其具體的反映就是window)
console.log(this === window) //true
//node(在node裏面,全局對象global具像化了,真正指代全局對象)
//1. 文件裏
console.log(this) //{}
//2. 命令行裏
console.log(global) // ...
// => node文件中的this不是global
閉包
//node
console.log(this)
var a = 1
console.log(this.a) //undifined
a = 1
console.log(global.a) //在這個文件環境裏面找不到a就會向上找到全局global, a=1
//類似於
var a = 1
function(){
a = 1
console.log(global.a)
}
//模塊對應的閉包函數的參數
console.log(arguments)
導出文件的具體實現
//exports內存中指向的就是module.exports指向的那塊空間
//require一個方法
//Module模塊類
//__filename該文件絕對路徑
//__dirname該文件父文件夾的絕對路徑
(function(exports,require,Module,__filename,__dirname){
module.exports = exports = this = {}
//文件中的所有代碼
//不能改變exports指向,因爲返回的是module.exports,所以是個{}
return module.exports
})
所以我們require的時候其實就相當於執行了這麼一個閉包,然後返回的就是我們的module.exports。
require是怎麼樣的?
- 每個模塊都會帶一個require方法
- 動態加載(v8執行到這一步纔會去加載此模塊)
- 不同模塊的類別,有不同的加載方式,一般有三種常用後綴
– 後綴名爲.js的JavaScript腳本文件,需要先讀入內存再運行
– 後綴名爲.json的JSON文件,fs 讀入內存 轉化成JSON對象
– 後綴名爲.node的經過編譯後的二進制C/C++擴展模塊文件,可以 - 查找第三方模塊
– 如果require函數只指定名稱則視爲從node_modules下面加載文件,這樣的話你可以移動模塊而不需要修改引用的模塊路徑。
第三方模塊的查詢路徑包括module.paths和全局目錄。
關於閉包
js權威指南
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
var foo = checkscope();
foo();
作用域鏈
f = { Scope: [AO, checkscope, global] }
就是因爲這個作用域鏈,f 函數依然可以讀取到 checkscope.AO
的值,說明當 f 函數引用了 checkscope.AO
中的值的時候,即使 checkscope
被銷燬了,但是 JavaScript 依然會讓checkscope.AO
活在內存中,f 函數依然可以通過 f 函數的作用域鏈找到它,正是因爲 JavaScript 做到了這一點,從而實現了閉包這個概念。
即使創建它的上下文已經銷燬,它仍然存在(比如,內部函數從父函數中返回)