iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0

什麼是模塊??

好的作者將他們的書分為章節,一個好的團隊需要分工合作,一個優秀的工程師需要將他們的程式分為模塊。

前端的模塊就是後端的namespace的意思,主要可以避免變數全域汙染。

好的模塊應該是高度獨立的,也就是說應該只負責一個功能。所以根據需求修改他們時,並不會破壞整個架構。

為什麼要使用模塊??

  1. 可維護性:

當我們將模塊設計的越獨立,修改需求時。即不用擔心發生牽一髮動全身,整組代碼壞光光的悲劇。

就像是今天球鞋的鞋帶壞了,我們直接換掉鞋帶就好。不需要整雙球鞋換掉。因為鞋體與鞋帶是互相獨立的。

  1. 命名空間:

在JavaScript中,全局變量(意味著每個人都可以訪問它們)衝突是最令人頭痛的一件事。常會發生於不同套件影響到的相同全域變量時、或是我們自己的使用的全域變量與套件的變量相同時。

在不相關的代碼之間共享全局變量是開發中的一個大問題。而模塊這個機制允許我們通過為變量創建私有空間來避免名稱空間污染。

  1. 可重用性:
    當我們已經將先前編寫的代碼複製到了一個新的項目中。例如,假設您將從先前項目編寫的一些實用程序方法複製到當前項目。
    一切都很好,但是,如果您找到一種更好的方式來編寫該代碼的某些部分,則必須回過頭來,並記住要在其他所有編寫代碼的地方對其進行更新。
    這非常浪費時間。如果有一個-等待它-我們可以一遍又一遍地重用的模塊,難道不是容易得多嗎?

模塊模式範例

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是唯一的全局變量。
而這種方法使我們能夠決定將哪些變量/方法保持私有狀態,(類似的方法有非常多,這裡先舉兩個例子)
,這些方法有一個共同點:使用單個全局變量將其代碼包裝在函數中,從而使用閉包作用域為其自身創建私有名稱空間。
但是他們依然有缺點

  1. 作為開發人員,您需要知道正確的依賴順序來加載文件。例如,假設您在項目中使用jQuery validate,因此在文件中包含jQuery validate源代碼的腳本標籤。
    但是,由於jQuery validate嚴格依賴jQuery,因此jQuery validate文件的腳本標籤不能放在jQuery文件之前。

  2. 它們仍然可能導致名稱空間衝突。例如,如果您的兩個模塊具有相同的名稱怎麼辦?(例如: jQuery的名稱是$,而另一個套件的名稱也是$)。

Answer:CommonJS和AMD。

CommonJs AMD UMD

模塊本質上是一種可重複使用的一段JavaScript代碼其中出口特定對象,使它們可用於其他模塊需要在他們的計劃。
與我們之前討論的模塊模式相比,他們有兩個明顯的好處:

1.避免全局命名空間污染
2.明確我們的依賴關係

  • 需要注意的是CommonJS採用服務器優先的方法並同步加載模塊 這在服務器上可以很好地工作,但是不幸的是,這使得為瀏覽器編寫JavaScript時更難使用。
  • 而AMD採用了瀏覽器優先的方法以及異步行為來完成工作。
  • UMD本質上創建了使用這兩種方法之一的方式,同時還支持全局變量定義。結果,UMD模塊能夠在客戶端和服務器上工作。

這裡來一點 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)


上一篇
JS小精靈 babel -4
下一篇
模組化工具webpack
系列文
想成為超級開源貢獻者嗎 ? 新手也能用Javascript寫出專業高效能的"新世代"開源庫30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言