javasript require與import詳解

javasript require與import詳解

前言

在javascript中,導(dǎo)入模塊可使用require或者import,但兩者之間有什么區(qū)別呢?

產(chǎn)生背景

要弄清兩者之間的區(qū)別,首先需要弄明白兩者是如何產(chǎn)生的,同樣是導(dǎo)入模塊,為何要定義兩個關(guān)鍵字?

下面這張圖可以很好的說明require與import之間的關(guān)聯(lián)

企業(yè)微信截圖_163852141824.png

require與module.exports是一對,它們是CommonJS中定義的關(guān)鍵字;import與export是一對,它們是ES6定義的標準;它們產(chǎn)生的原因都是為了讓javascript項目可以模塊化,使js不只是能在瀏覽器端編寫一些簡單的腳本,還可以運用js編寫更加龐大的項目。

下面有對模塊化更加詳細的解釋:

什么是模塊化?
模塊化就是將變量和函數(shù) 放入不同的文件中 
模塊的作用域是私有的 內(nèi)部定義的代碼只能在當前文件中使用 外部使用那么需要將此模塊暴露出去

模塊化的好處:
減少全局變量  
避免變量名和函數(shù)命名沖突
提高代碼的復(fù)用性和維護性

到這里,可能又會有小伙伴產(chǎn)生疑問了,CommonJS與ES6又有什么區(qū)別與聯(lián)系?

  • CommonJS是由JavaScript社區(qū)創(chuàng)造并維護的,CommonJS代碼并不能直接在瀏覽器運行,需要通過第三方庫進行轉(zhuǎn)義才行

    CommonJS產(chǎn)生的原因
    
    JavaScript是一個強大面向?qū)ο笳Z言,它有很多快速高效的解釋器。官方JavaScript標準定義的API是為了構(gòu)建基于瀏覽器的應(yīng)用程序。然而,并沒有定于一個用于更廣泛的應(yīng)用程序的標準庫。CommonJS API定義很多普通應(yīng)用程序(主要指非瀏覽器的應(yīng)用)使用的API,從而填補了這個空白。它的終極目標是提供一個類似Python,Ruby和Java標準庫。這樣的話,開發(fā)者可以使用CommonJS API編寫應(yīng)用程序,然后這些應(yīng)用可以運行在不同的JavaScript解釋器和不同的主機環(huán)境中。在兼容CommonJS的系統(tǒng)中,你可以實用JavaScript程序開發(fā):服務(wù)器端JavaScript應(yīng)用程序命令行工具、圖形界面應(yīng)用程序、混合應(yīng)用程序(如,Titanium或Adobe AIR)
    
  • ECMAScript 6(以下簡稱ES6)是JavaScript語言的下一代標準,已經(jīng)在2015年6月正式發(fā)布了,ES6代碼可以直接在現(xiàn)代瀏覽器上運行

    ECMAScript和JavaScript到底是什么關(guān)系?簡單來說,ECMAScript是JavaScript語言的國際標準,JavaScript是ECMAScript的實現(xiàn)。
    1996年11月,JavaScript的創(chuàng)造者Netscape公司,決定將JavaScript提交給國際標準化組織ECMA,希望這種語言能夠成為國際標準。次年,ECMA發(fā)布262號標準文件(ECMA-262)的第一版,規(guī)定了瀏覽器腳本語言的標準,并將這種語言稱為ECMAScript。這個版本就是ECMAScript 1.0版。
    ES6的目標,是使得JavaScript語言可以用來編寫大型的復(fù)雜的應(yīng)用程序,成為企業(yè)級開發(fā)語言。
    

CommonJS很早就產(chǎn)生了,nodejs就是基于CommonJS進行開發(fā)的(為什么不使用ES6?因為ES6還沒發(fā)布),因此在使用nodejs編寫代碼時,使用的是require與module.exports,對于兩者,有一句比較有趣的外文解釋:

I will make it simple,

Import and Export are ES6 features(Next gen JS).
Require is old school method of importing code from other files

代碼中的表現(xiàn)

在vue項目中,使用require與import都可以導(dǎo)入模塊,那么它們之間的差異是什么呢?

  • require一定要配合module.exports使用,import則需要和export配合使用,它們之間不能交叉,否則將會報錯

    // a.js
    const a = 100;
    module.exports = { a };
    
    // b.js
    const { a } = require('./b');
    console.log(a); // 輸出100
    
    // a.js
    const a = 100;
    export default a;
    
    // b.js
    import a from './a';
    console.log(a); // 輸出100
    
  • require只會在第一次加載時運行,之后加載都是直接獲取緩存(導(dǎo)出對象)

    // a.js
    console.log("a");
    
    // b.js
    require("./a.js");
    
    // c.js
    require("./a.js");
    require("./b.js");
    
    // 輸出: a
    

    雖然導(dǎo)入了兩次 a.js,結(jié)果只有打印了一次a

  • require的導(dǎo)出不是動態(tài)綁定的

    // a.js
    let counter = 0;
    function incCounter() {
      counter++;
    }
    
    module.exports = { counter, incCounter };
    
    // b.js
    const { counter, incCounter } = require("./a.js");
    
    console.log(counter);
    incCounter();
    console.log(counter);
    
    // 輸出:0 0
    

    打印結(jié)果均為 0

  • import用于異步加載,返回一個 Promise 對象,只會在第一次加載時運行

    // a.mjs
    console.log("a");
    
    // b.mjs
    import "./a.mjs";
    
    // c.mjs
    import "./a.mjs";
    import "./b.mjs";
    
    // 輸出:a
    

    雖然導(dǎo)入了兩次 a.mjs,但是只打印了一次 a

  • import的數(shù)據(jù)是動態(tài)綁定的

    // a.mjs
    let counter = 0;
    function incCounter() {
      counter++;
    }
    
    export { counter, incCounter };
    
    // b.mjs
    import { counter, incCounter } from "./a.mjs";
    
    console.log(counter);
    incCounter();
    console.log(counter);
    
    //輸出:0 1
    

    a.js中的變量變化同步映射到了b.js

總結(jié)

import與require在第一次導(dǎo)入模塊時都會執(zhí)行模塊代碼,多次導(dǎo)入不會重復(fù)執(zhí)行,兩者的區(qū)別在于require會緩存首次的結(jié)果,import導(dǎo)出的是一個Promise

在vue開發(fā)中建議使用import與export,畢竟require算是較為過時了,node在未來的規(guī)劃中,也計劃推出對ES6語法的支持,import與export才是未來

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容