好的作者將他們的書分為章節,一個好的團隊需要分工合作,一個優秀的工程師需要將他們的程式分為模塊。
前端的模塊就是後端的namespace的意思,主要可以避免變數全域汙染。
好的模塊應該是高度獨立的,也就是說應該只負責一個功能。所以根據需求修改他們時,並不會破壞整個架構。
當我們將模塊設計的越獨立,修改需求時。即不用擔心發生牽一髮動全身,整組代碼壞光光的悲劇。
就像是今天球鞋的鞋帶壞了,我們直接換掉鞋帶就好。不需要整雙球鞋換掉。因為鞋體與鞋帶是互相獨立的。
在JavaScript中,全局變量(意味著每個人都可以訪問它們)衝突是最令人頭痛的一件事。常會發生於不同套件影響到的相同全域變量時、或是我們自己的使用的全域變量與套件的變量相同時。
在不相關的代碼之間共享全局變量是開發中的一個大問題。而模塊這個機制允許我們通過為變量創建私有空間來避免名稱空間污染。
Module模式用於模仿類的概念(因為JavaScript是一個沒有類別的語言,雖然他有很多模擬類的方法,但是他沒有類。)
但是一樣有幾種方法可以完成模塊模式。
在第一個示例中,我將使用匿名閉包。通過將所有代碼放入匿名函數中,這將幫助我們實現目標。
var global = "12";
(function () {
//這裡的變量都是private
var word = "Hello";
function getWord(){
return word;
}
console.log(getWord());
//這裡依樣訪問的到全局變量喔
console.log(global);
}());
// 'Hello'
// 12
: 全局導入
(function (globalVariable) {
// Keep this variables private inside this closure scope
var privateFunction = function() {
console.log('Shhhh, this is private!');
}
// Expose the below methods via the globalVariable interface while
// hiding the implementation of the method within the
// function() block
globalVariable.each = function(collection, iterator) {
if (Array.isArray(collection)) {
for (var i = 0; i < collection.length; i++) {
iterator(collection[i], i, collection);
}
} else {
for (var key in collection) {
iterator(collection[key], key, collection);
}
}
};
globalVariable.filter = function(collection, test) {
var filtered = [];
globalVariable.each(collection, function(item) {
if (test(item)) {
filtered.push(item);
}
});
return filtered;
};
globalVariable.map = function(collection, iterator) {
var mapped = [];
globalUtils.each(collection, function(value, key, collection) {
mapped.push(iterator(value));
});
return mapped;
};
globalVariable.reduce = function(collection, iterator, accumulator) {
var startingValueMissing = accumulator === undefined;
globalVariable.each(collection, function(item) {
if(startingValueMissing) {
accumulator = item;
startingValueMissing = false;
} else {
accumulator = iterator(accumulator, item);
}
});
return accumulator;
};
}(globalVariable));
在此示例中,globalVariable是唯一的全局變量。
而這種方法使我們能夠決定將哪些變量/方法保持私有狀態,(類似的方法有非常多,這裡先舉兩個例子)
,這些方法有一個共同點:使用單個全局變量將其代碼包裝在函數中,從而使用閉包作用域為其自身創建私有名稱空間。
但是他們依然有缺點
作為開發人員,您需要知道正確的依賴順序來加載文件。例如,假設您在項目中使用jQuery validate,因此在文件中包含jQuery validate源代碼的腳本標籤。
但是,由於jQuery validate嚴格依賴jQuery,因此jQuery validate文件的腳本標籤不能放在jQuery文件之前。
它們仍然可能導致名稱空間衝突。例如,如果您的兩個模塊具有相同的名稱怎麼辦?(例如: jQuery的名稱是$,而另一個套件的名稱也是$)。
模塊本質上是一種可重複使用的一段JavaScript代碼其中出口特定對象,使它們可用於其他模塊需要在他們的計劃。
與我們之前討論的模塊模式相比,他們有兩個明顯的好處:
1.避免全局命名空間污染
2.明確我們的依賴關係
這裡來一點 CommonJs AMD UMD 的範例
CommonJs
function myModule() {
this.hello = function() {
return 'hello!';
}
this.goodbye = function() {
return 'goodbye!';
}
}
module.exports = myModule;
AMD
define(['myModule', 'myOtherModule'], function(myModule, myOtherModule) {
console.log(myModule.hello());
});
UMD
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['myModule', 'myOtherModule'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('myModule'), require('myOtherModule'));
} else {
// Browser globals (Note: root is window)
root.returnExports = factory(root.myModule, root.myOtherModule);
}
}(this, function (myModule, myOtherModule) {
// Methods
function notHelloOrGoodbye(){}; // A private method
function hello(){}; // A public method because it's returned (see below)
function goodbye(){}; // A public method because it's returned (see below)
// Exposed public methods
return {
hello: hello,
goodbye: goodbye
}
}));
今天先介紹了幾總模塊模塊,模塊很好玩吧,明天將會逐步解釋模塊打包工具喔
webpack 官網 (https://webpack.docschina.org/concepts/)
JavaScript Modules: A Beginner’s Guide(https://www.freecodecamp.org/news/javascript-modules-a-beginner-s-guide-783f7d7a5fcc/#.jw1txw6uh)