国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript 是如何工作的:模塊的構(gòu)建以及對應(yīng)的打包工具

hedzr / 2554人閱讀

摘要:掛機(jī)科了次使用這個結(jié)構(gòu),匿名函數(shù)就有了自己的執(zhí)行環(huán)境或閉包,然后我們立即執(zhí)行。注意,匿名函數(shù)的圓括號是必需的,因為以關(guān)鍵字開頭的語句通常被認(rèn)為是函數(shù)聲明請記住,中不能使用未命名的函數(shù)聲明。

這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 20 篇。

想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!

如果你錯過了前面的章節(jié),可以在這里找到它們:

JavaScript 是如何工作的:引擎,運(yùn)行時和調(diào)用堆棧的概述!

JavaScript 是如何工作的:深入V8引擎&編寫優(yōu)化代碼的5個技巧!

JavaScript 是如何工作的:內(nèi)存管理+如何處理4個常見的內(nèi)存泄漏!

JavaScript 是如何工作的:事件循環(huán)和異步編程的崛起+ 5種使用 async/await 更好地編碼方式!

JavaScript 是如何工作的:深入探索 websocket 和HTTP/2與SSE +如何選擇正確的路徑!

JavaScript 是如何工作的:與 WebAssembly比較 及其使用場景!

JavaScript 是如何工作的:Web Workers的構(gòu)建塊+ 5個使用他們的場景!

JavaScript 是如何工作的:Service Worker 的生命周期及使用場景!

JavaScript 是如何工作的:Web 推送通知的機(jī)制!

JavaScript 是如何工作的:使用 MutationObserver 跟蹤 DOM 的變化!

JavaScript 是如何工作的:渲染引擎和優(yōu)化其性能的技巧!

JavaScript 是如何工作的:深入網(wǎng)絡(luò)層 + 如何優(yōu)化性能和安全!

JavaScript 是如何工作的:CSS 和 JS 動畫底層原理及如何優(yōu)化它們的性能!

JavaScript 是如何工作的:解析、抽象語法樹(AST)+ 提升編譯速度5個技巧!

JavaScript 是如何工作的:深入類和繼承內(nèi)部原理+Babel和 TypeScript 之間轉(zhuǎn)換!

JavaScript 是如何工作的:存儲引擎+如何選擇合適的存儲API!

JavaScript 是如何工作的:Shadow DOM 的內(nèi)部結(jié)構(gòu)+如何編寫?yīng)毩⒌慕M件!

JavaScript 是如何工作的:WebRTC 和對等網(wǎng)絡(luò)的機(jī)制!

JavaScript 是如何工作的:編寫自己的 Web 開發(fā)框架 + React 及其虛擬 DOM 原理!

如果你是 JavaScript 的新手,一些像 “module bundlers vs module loaders”、“Webpack vs Browserify” 和 “AMD vs.CommonJS” 這樣的術(shù)語,很快讓你不堪重負(fù)。

JavaScript 模塊系統(tǒng)可能令人生畏,但理解它對 Web 開發(fā)人員至關(guān)重要。

在這篇文章中,我將以簡單的言語(以及一些代碼示例)為你解釋這些術(shù)語。 希望這對你有會有幫助!

什么是模塊?

好作者能將他們的書分成章節(jié),優(yōu)秀的程序員將他們的程序劃分為模塊。

就像書中的章節(jié)一樣,模塊只是文字片段(或代碼,視情況而定)的集群。然而,好的模塊是高內(nèi)聚低松耦的,具有不同的功能,允許在必要時對它們進(jìn)行替換、刪除或添加,而不會擾亂整體功能。

為什么使用模塊?

使用模塊有利于擴(kuò)展、相互依賴的代碼庫,這有很多好處。在我看來,最重要的是:

1)可維護(hù)性: 根據(jù)定義,模塊是高內(nèi)聚的。一個設(shè)計良好的模塊旨在盡可能減少對代碼庫部分的依賴,這樣它就可以獨(dú)立地增強(qiáng)和改進(jìn),當(dāng)模塊與其他代碼片段解耦時,更新單個模塊要容易得多。

回到我們的書的例子,如果你想要更新你書中的一個章節(jié),如果對一個章節(jié)的小改動需要你調(diào)整每一個章節(jié),那將是一場噩夢。相反,你希望以這樣一種方式編寫每一章,即可以在不影響其他章節(jié)的情況下進(jìn)行改進(jìn)。

2)命名空間: 在 JavaScript 中,頂級函數(shù)范圍之外的變量是全局的(這意味著每個人都可以訪問它們)。因此,“名稱空間污染”很常見,完全不相關(guān)的代碼共享全局變量。

在不相關(guān)的代碼之間共享全局變量在開發(fā)中是一個大禁忌。正如我們將在本文后面看到的,通過為變量創(chuàng)建私有空間,模塊允許我們避免名稱空間污染。

3)可重用性:坦白地說:我們將前寫過的代碼復(fù)制到新項目中。 例如,假設(shè)你從之前項目編寫的一些實用程序方法復(fù)制到當(dāng)前項目中。

這一切都很好,但如果你找到一個更好的方法來編寫代碼的某些部分,那么你必須記得回去在曾經(jīng)使用過的其他項目更新它。

這顯然是在浪費(fèi)時間。如果有一個我們可以一遍又一遍地重復(fù)使用的模塊,不是更容易嗎?

如何創(chuàng)建模塊?

有多種方法來創(chuàng)建模塊,來看幾個:

模塊模式

模塊模式用于模擬類的概念(因為 JavaScript 本身不支持類),因此我們可以在單個對象中存儲公共和私有方法和變量——類似于在 Java 或 Python 等其他編程語言中使用類的方式。這允許我們?yōu)橄胍_的方法創(chuàng)建一個面向公共的 API,同時仍然將私有變量和方法封裝在閉包范圍中。

有幾種方法可以實現(xiàn)模塊模式。在第一個示例中,將使用匿名閉包,將所有代碼放在匿名函數(shù)中來幫助我們實現(xiàn)目標(biāo)。(記住:在 JavaScript 中,函數(shù)是創(chuàng)建新作用域的唯一方法。)

例一:匿名閉包

(function () {
  // 將這些變量放在閉包范圍內(nèi)實現(xiàn)私有化
  
  var myGrades = [93, 95, 88, 0, 55, 91];
  
  var average = function() {
    var total = myGrades.reduce(function(accumulator, item) {
      return accumulator + item}, 0);
    
      return "平均分 " + total / myGrades.length + ".";
  }

  var failing = function(){
    var failingGrades = myGrades.filter(function(item) {
      return item < 70;});
      
    return "掛機(jī)科了 " + failingGrades.length + " 次。";
  }

  console.log(failing()); // 掛機(jī)科了次

}());


使用這個結(jié)構(gòu),匿名函數(shù)就有了自己的執(zhí)行環(huán)境或“閉包”,然后我們立即執(zhí)行。這讓我們可以從父(全局)命名空間隱藏變量。

這種方法的優(yōu)點是,你可以在這個函數(shù)中使用局部變量,而不會意外地覆蓋現(xiàn)有的全局變量,但仍然可以訪問全局變量,就像這樣:

    var global = "你好,我是一個全局變量。)";
    
   (function () {
      // 將這些變量放在閉包范圍內(nèi)實現(xiàn)私有化
      
      var myGrades = [93, 95, 88, 0, 55, 91];
      
      var average = function() {
        var total = myGrades.reduce(function(accumulator, item) {
          return accumulator + item}, 0);
        
          return "平均分 " + total / myGrades.length + ".";
      }
    
      var failing = function(){
        var failingGrades = myGrades.filter(function(item) {
          return item < 70;});
          
        return "掛機(jī)科了 " + failingGrades.length + " 次。";
      }
    
      console.log(failing()); // 掛機(jī)科了次
      onsole.log(global); // 你好,我是一個全局變量。
    
    }());

注意,匿名函數(shù)的圓括號是必需的,因為以關(guān)鍵字 function 開頭的語句通常被認(rèn)為是函數(shù)聲明(請記住,JavaScript 中不能使用未命名的函數(shù)聲明)。因此,周圍的括號將創(chuàng)建一個函數(shù)表達(dá)式,并立即執(zhí)行這個函數(shù),這還有另一種叫法 立即執(zhí)行函數(shù)(IIFE)。如果你對這感興趣,可以在這里了解到更多。

例二:全局導(dǎo)入

jQuery 等庫使用的另一種流行方法是全局導(dǎo)入。它類似于我們剛才看到的匿名閉包,只是現(xiàn)在我們作為參數(shù)傳入全局變量:

(function (globalVariable) {

  // 在這個閉包范圍內(nèi)保持變量的私有化
  var privateFunction = function() {
    console.log("Shhhh, this is private!");
  }

  // 通過 globalVariable 接口公開下面的方法
 // 同時將方法的實現(xiàn)隱藏在 function() 塊中

  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 是唯一的全局變量。與匿名閉包相比,這種方法的好處是可以預(yù)先聲明全局變量,使得別人更容易閱讀代碼。

例三:對象接口

另一種方法是使用立即執(zhí)行函數(shù)接口對象創(chuàng)建模塊,如下所示:

var myGradesCalculate = (function () {
    
  // 將這些變量放在閉包范圍內(nèi)實現(xiàn)私有化
  var myGrades = [93, 95, 88, 0, 55, 91];

  // 通過接口公開這些函數(shù),同時將模塊的實現(xiàn)隱藏在function()塊中

  return {
    average: function() {
      var total = myGrades.reduce(function(accumulator, item) {
        return accumulator + item;
        }, 0);
        
      return"平均分 " + total / myGrades.length + ".";
    },

    failing: function() {
      var failingGrades = myGrades.filter(function(item) {
          return item < 70;
        });

      return "掛科了" + failingGrades.length + " 次.";
    }
  }
})();

myGradesCalculate.failing(); // "掛科了 2 次." 
myGradesCalculate.average(); // "平均分 70.33333333333333."

正如您所看到的,這種方法允許我們通過將它們放在 return 語句中(例如算平均分和掛科數(shù)方法)來決定我們想要保留的變量/方法(例如 myGrades)以及我們想要公開的變量/方法。

例四:顯式模塊模式

這與上面的方法非常相似,只是它確保所有方法和變量在顯式公開之前都是私有的:

var myGradesCalculate = (function () {
    
  // 將這些變量放在閉包范圍內(nèi)實現(xiàn)私有化
  var myGrades = [93, 95, 88, 0, 55, 91];
  
  var average = function() {
    var total = myGrades.reduce(function(accumulator, item) {
      return accumulator + item;
      }, 0);
      
    return"平均分 " + total / myGrades.length + ".";
  };

  var failing = function() {
    var failingGrades = myGrades.filter(function(item) {
        return item < 70;
      });

    return "掛科了" + failingGrades.length + " 次.";
  };

  // Explicitly reveal public pointers to the private functions 
  // that we want to reveal publicly

  return {
    average: average,
    failing: failing
  }
})();

myGradesCalculate.failing(); // "掛科了 2 次." 
myGradesCalculate.average(); // "平均分 70.33333333333333."

這可能看起來很多,但它只是模塊模式的冰山一角。 以下是我在自己的探索中發(fā)現(xiàn)有用的一些資源:

Learning JavaScript Design Patterns:作者是 Addy Osmani,一本簡潔又令人印象深刻的書籍,蘊(yùn)藏著許多寶藏。

Adequately Good by Ben Cherry:包含模塊模式的高級用法示例。

Blog of Carl Danley:模塊模式概覽,也是 JavaScript 許多設(shè)計模式的資源庫。

CommonJS 和 AMD

所有這些方法都有一個共同點:使用單個全局變量將其代碼包裝在函數(shù)中,從而使用閉包作用域為自己創(chuàng)建一個私有名稱空間。

雖然每種方法都有效且都有各自特點,但卻都有缺點。

首先,作為開發(fā)人員,你需要知道加載文件的正確依賴順序。例如,假設(shè)你在項目中使用 Backbone,因此你可以將 Backbone 的源代碼 以

下面是幾個在瀏覽器中 構(gòu)建/轉(zhuǎn)換 ES6 模塊的方法,其中第一個是目前最常用的方法:

使用轉(zhuǎn)換器(例如 Babel 或 Traceur)以 CommonJS、AMD 或 UMD 格式將 ES6 代碼轉(zhuǎn)換為 ES5 代碼,然后再通過 Browserify 或 Webpack 一類的構(gòu)建工具來進(jìn)行構(gòu)建。

使用 Rollup.js,這其實和上面差不多,只是 Rollup 捎帶 ES6 模塊的功能,在打包之前靜態(tài)分析ES6 代碼和依賴項。 它利用 “tree shaking” 技術(shù)來優(yōu)化你的代碼。 總言,當(dāng)您使用ES6模塊時,Rollup.js 相對于 Browserify 或 Webpack 的主要好處是 tree shaking 能讓打包文件更小。 需要注意的是,Rollup提 供了幾種格式來的打包代碼,包括 ES6,CommonJS,AMD,UMD 或 IIFE。 IIFE 和 UMD 捆綁包可以直接在瀏覽器中工作,但如果你選擇打包 AMD,CommonJS 或 ES6,需需要尋找能將代碼轉(zhuǎn)成瀏覽器能理解運(yùn)行的代碼的方法(例如,使用 Browserify, Webpack,RequireJS等)。

小心踩坑

作為 web 開發(fā)人員,我們必須經(jīng)歷很多困難。轉(zhuǎn)換語法優(yōu)雅的ES6代碼以便在瀏覽器里運(yùn)行并不總是容易的。

問題是,什么時候 ES6 模塊可以在瀏覽器中運(yùn)行而不需要這些開銷?

答案是:“盡快”。

ECMAScript 目前有一個解決方案的規(guī)范,稱為 ECMAScript 6 module loader API。簡而言之,這是一個綱領(lǐng)性的、基于 Promise 的 API,它支持動態(tài)加載模塊并緩存它們,以便后續(xù)導(dǎo)入不會重新加載模塊的新版本。

它看起來如下:

// myModule.js

export class myModule {
  constructor() {
    console.log("Hello, I am a module");
  }

  hello() {
    console.log("hello!");
  }

  goodbye() {
    console.log("goodbye!");
  }
}


 // main.js
System.import(‘myModule’).then(function(myModule) {
  new myModule.hello();
});

// ‘hello!’

你亦可直接對 script 標(biāo)簽指定 “type=module” 來定義模塊,如:



更加詳細(xì)的介紹也可以在 Github 上查看:es-module-loader

此外,如果您想測試這種方法,請查看 SystemJS,它建立在 ES6 Module Loader polyfill 之上。 SystemJS 在瀏覽器和 Node 中動態(tài)加載任何模塊格式(ES6模塊,AMD,CommonJS 或 全局腳本)。

它跟蹤“模塊注冊表”中所有已加載的模塊,以避免重新加載先前已加載過的模塊。 更不用說它還會自動轉(zhuǎn)換ES6模塊(如果只是設(shè)置一個選項)并且能夠從任何其他類型加載任何模塊類型!

有了原生的 ES6 模塊后,還需要模塊打包嗎?

對于日益普及的 ES6 模塊,下面有一些有趣的觀點:

HTTP/2 會讓模塊打包過時嗎?

對于 HTTP/1,每個TCP連接只允許一個請求。這就是為什么加載多個資源需要多個請求。有了 HTTP/2,一切都變了。HTTP/2 是完全多路復(fù)用的,這意味著多個請求和響應(yīng)可以并行發(fā)生。因此,我們可以在一個連接上同時處理多個請求。

由于每個 HTTP 請求的成本明顯低于HTTP/1,因此從長遠(yuǎn)來看,加載一組模塊不會造成很大的性能問題。一些人認(rèn)為這意味著模塊打包不再是必要的,這當(dāng)然有可能,但這要具體情況具體分析了。

例如,模塊打包還有 HTTP/2 沒有好處,比如移除冗余的導(dǎo)出模塊以節(jié)省空間。 如果你正在構(gòu)建一個性能至關(guān)重要的網(wǎng)站,那么從長遠(yuǎn)來看,打包可能會為你帶來增量優(yōu)勢。 也就是說,如果你的性能需求不是那么極端,那么通過完全跳過構(gòu)建步驟,可以以最小的成本節(jié)省時間。

總的來說,絕大多數(shù)網(wǎng)站都用上 HTTP/2 的那個時候離我們現(xiàn)在還很遠(yuǎn)。我預(yù)測構(gòu)建過程將會保留,至少在近期內(nèi)。

CommonJS、AMD 與 UMD 會被淘汰嗎?

一旦 ES6 成為模塊標(biāo)準(zhǔn),我們還需要其他非原生模塊規(guī)范嗎?

我覺得還有。

Web 開發(fā)遵守一個標(biāo)準(zhǔn)方法進(jìn)行導(dǎo)入和導(dǎo)出模塊,而不需要中間構(gòu)建步驟——網(wǎng)頁開發(fā)長期受益于此。但 ES6 成為模塊規(guī)范需要多長時間呢?

機(jī)會是有,但得等一段時間 。

再者,眾口難調(diào),所以“一個標(biāo)準(zhǔn)的方法”可能永遠(yuǎn)不會成為現(xiàn)實。

總結(jié)

希望這篇文章能幫你理清一些開發(fā)者口中的模塊和模塊打包的相關(guān)概念,共進(jìn)步。

原文:

https://medium.freecodecamp.o...

https://medium.freecodecamp.o...

你的點贊是我持續(xù)分享好東西的動力,歡迎點贊!

交流

干貨系列文章匯總?cè)缦拢X得不錯點個Star,歡迎 加群 互相學(xué)習(xí)。

https://github.com/qq44924588...

我是小智,公眾號「大遷世界」作者,對前端技術(shù)保持學(xué)習(xí)愛好者。我會經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!

關(guān)注公眾號,后臺回復(fù)福利,即可看到福利,你懂的。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101765.html

相關(guān)文章

  • Javascript五十問——從源頭細(xì)說Webpack與Gulp

    摘要:前言與是目前圈子內(nèi)比較活躍的前端構(gòu)建工具。對于初學(xué)者來說,對這二者往往容易認(rèn)識不清,今天,就從事件的源頭,說清楚與。它可以將許多松散的模塊按照依賴和規(guī)則打包成符合生產(chǎn)環(huán)境部署的前端資源。打包后形成的文件出口。 前言:Webpack 與 gulp是目前圈子內(nèi)比較活躍的前端構(gòu)建工具。網(wǎng)上有很多二者比較的文章,面試中也會經(jīng)常遇到gulp,Webpack的區(qū)別這樣的問題。對于初學(xué)者來說,對這二...

    lwx12525 評論0 收藏0
  • 新一代打包神器parcel簡介

    摘要:友好的錯誤記錄體驗,語法突出顯示的代碼幀有助于查明問題。為入口資源創(chuàng)建一個,并為動態(tài)導(dǎo)入的資源創(chuàng)建子,這回導(dǎo)致代碼拆分的發(fā)生。如果一個資源需要多個,它會被打包到最近的共同祖先,因此它不會被包含多次。 官方地址:https://parceljs.org/getting_... Parcel 是 Web 應(yīng)用打包工具,適用于經(jīng)驗不同的開發(fā)者。它利用多核處理提供了極快的速度,并且不需要任何...

    Jenny_Tong 評論0 收藏0
  • 宣布 Parcel:一個快速,零配置 Web 應(yīng)用打包工具 ?

    摘要:宣布一個快速,零配置的應(yīng)用打包工具原文譯者今天,我非常高興地宣布,一個快速,零配置的應(yīng)用程序打包工具,我對于該工具的工作已經(jīng)持續(xù)了幾個月。性能我被激發(fā)建立一個新的打包工具的第一個原因是性能。 ? 宣布 Parcel:一個快速,零配置的 Web 應(yīng)用打包工具 ? 原文:? Announcing Parcel: A blazing fast, zero configuration web...

    learn_shifeng 評論0 收藏0
  • webpack 3 零基礎(chǔ)入門教程 #1 - 介紹

    摘要:所以它在某些程度上,跟的功能有些相同。嚴(yán)格上講,模塊化不是他強(qiáng)調(diào)的東西,他旨在規(guī)范前端開發(fā)流程。更是明顯強(qiáng)調(diào)模塊化開發(fā),而那些文件壓縮合并預(yù)處理等功能,不過是他附帶的功能。 1. webpack 是什么? showImg(https://segmentfault.com/img/remote/1460000012293461); 先來說一下 webpack 是什么。 webpack 的...

    張紅新 評論0 收藏0
  • 聊聊webpack

    摘要:但是由于缺乏規(guī)范化管理,出現(xiàn)了很多種模塊化規(guī)范,從針對的規(guī)范,到針對瀏覽器端的,終于在里規(guī)范了前端模塊化。可以通過兩種方式之一終端或。導(dǎo)出多個配置對象運(yùn)行時,所有的配置對象都會構(gòu)建。在階段又會發(fā)生很多小事件。 隨著前端的迅速發(fā)展,web項目復(fù)雜度也是越來越高。為了便捷開發(fā)和利于優(yōu)化,將一個復(fù)雜項目拆分成一個個小的模塊,于是模塊化開發(fā)出現(xiàn)了。但是由于缺乏規(guī)范化管理,出現(xiàn)了很多種模塊化規(guī)范...

    Ashin 評論0 收藏0

發(fā)表評論

0條評論

hedzr

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<