require import區(qū)別

1. 出現(xiàn)的時(shí)間贺纲、地點(diǎn)不同

年份 出處
require/exports 2009 CommonJS
import/export 2015 ECMAScript2015(ES6)

2. 不同端(客戶端/服務(wù)器)的使用限制

require/exports import/export
Node.js 所有版本 Node 9.0+(啟動(dòng)需加上 flag --experimental-modules)Node 13.2+(直接啟動(dòng))
Chrome 不支持 61+
Firefox 不支持 60+
Safari 不支持 10.1+
Edge 不支持 16+

CommonJS 模塊化方案 require/exports 是為服務(wù)器端開發(fā)設(shè)計(jì)的。服務(wù)器模塊系統(tǒng)同步讀取模塊文件內(nèi)容,編譯執(zhí)行后得到模塊接口啤贩。(Node.js 是 CommonJS 規(guī)范的實(shí)現(xiàn))。

在瀏覽器端,因?yàn)槠?strong>異步加載腳本文件的特性,CommonJS 規(guī)范無法正常加載焰坪。所以出現(xiàn)了 RequireJS、SeaJS 等(兼容 CommonJS )為瀏覽器設(shè)計(jì)的模塊化方案聘惦。直到 ES6 規(guī)范出現(xiàn)某饰,瀏覽器才擁有了自己的模塊化方案 import/export。

兩種方案各有各的限制善绎,需要注意以下幾點(diǎn):

  • 原生瀏覽器不支持 require/exports黔漂,可使用支持 CommonJS 模塊規(guī)范的 Browsersify、webpack 等打包工具禀酱,它們會(huì)將 require/exports 轉(zhuǎn)換成能在瀏覽器使用的代碼炬守。
  • import/export 在瀏覽器中無法直接使用,我們需要在引入模塊的 <script> 元素上添加type="module" 屬性剂跟。
  • 即使 Node.js 13.2+ 可以通過修改文件后綴為 .mjs 來支持 ES6 模塊 import/export减途,但是Node.js 官方不建議在正式環(huán)境使用。目前可以使用 babel 將 ES6 的模塊系統(tǒng)編譯成 CommonJS 規(guī)范(注意:語法一樣曹洽,但具體實(shí)現(xiàn)還是 require/exports)鳍置。

3. require/exports 是運(yùn)行時(shí)動(dòng)態(tài)加載,import/export 是靜態(tài)編譯

CommonJS 加載的是一個(gè)對(duì)象(即 module.exports 屬性)送淆,該對(duì)象只有在腳本運(yùn)行完才會(huì)生成税产。而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成辟拷。- 阮一峰

4. require/exports 輸出的是一個(gè)值的拷貝撞羽,import/export 模塊輸出的是值的引用

require/exports 輸出的是值的拷貝。也就是說衫冻,一旦輸出一個(gè)值诀紊,模塊內(nèi)部的變化就影響不到這個(gè)值。

import/export 模塊輸出的是值的引用隅俘。JS 引擎對(duì)腳本靜態(tài)分析的時(shí)候渡紫,遇到模塊加載命令import,就會(huì)生成一個(gè)只讀引用考赛。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用莉测,到被加載的那個(gè)模塊里面去取值颜骤。

若文件引用的模塊值改變,require 引入的模塊值不會(huì)改變捣卤,而 import 引入的模塊值會(huì)改變忍抽。

5. 用法不一致

(1). require/exports 的用法

const fs = require('fs')
exports.fs = fs
module.exports = fs

exports 是對(duì) module.exports 的引用,相當(dāng)于

exports = module.exports = {};

在不改變 exports 指向的情況下董朝,使用 exports 和 module.exports 沒有區(qū)別鸠项;如果將 exports 指向了其他對(duì)象,exports 改變不會(huì)改變模塊輸出值子姜。示例如下:

//utils.js
let a = 100;

exports.a = 200;
console.log(module.exports) //{a : 200}
exports = {a:300}; //exports 指向其他內(nèi)存區(qū)

//test.js

var a = require('./utils');
console.log(a) // 打印為 {a : 200}

(2). import/export 的寫法

import fs from 'fs'
import {readFile} from 'fs' //從 fs 導(dǎo)入 readFile 模塊
import {default as fs} from 'fs' //從 fs 中導(dǎo)入使用 export default 導(dǎo)出的模塊
import * as fileSystem from 'fs' //從 fs 導(dǎo)入所有模塊祟绊,引用對(duì)象名為 fileSystem
import {readFile as read} from 'fs' //從 fs 導(dǎo)入 readFile 模塊,引用對(duì)象名為 read

export default fs
export const fs
export function readFile
export {readFile, read}
export * from 'fs'

建議1:建議明確列出我們要引用的內(nèi)容哥捕。牧抽,使用 * 雖然很方便,但是不利于現(xiàn)代的構(gòu)建工具檢測(cè)未被使用的函數(shù)遥赚,影響代碼優(yōu)化扬舒。

同時(shí)需要注意

  1. 引入 export default 導(dǎo)出的模塊不用加 {},引入非 export default 導(dǎo)出的模塊需要加 {}。
import fileSystem, {readFile} from 'fs'

2. 一個(gè)文件只能導(dǎo)出一個(gè) default 模塊凫佛。

3. 在驗(yàn)證代碼的時(shí)候遇到如下報(bào)錯(cuò)

access to script from origin 'null' has been blocked by CORS policy

前面提到過讲坎,瀏覽器引入模塊的 <script> 元素要添加 type="module 屬性,但 module 不支持 FTP 文件協(xié)議(file://)愧薛,只支持 HTTP 協(xié)議晨炕,所以本地需要使用 http-server 等本地網(wǎng)絡(luò)服務(wù)器打開網(wǎng)頁(yè)文件。

(3). import/export 不能對(duì)引入模塊重新賦值/定義

當(dāng)我嘗試給 import 的模塊重新賦值時(shí)

import {e1} from './webUtils.js';
  e1=234;

瀏覽器顯示

Uncaught TypeError: Assignment to constant variable.

當(dāng)我重新定義引用的模塊

import {e1} from './webUtils.js';
 var e1=1;

瀏覽器顯示

(index):17 Uncaught SyntaxError: Identifier 'e1' has already been declared

(4). ES6 模塊可以在 import 引用語句前使用模塊毫炉,CommonJS 則需要先引用后使用

ES6 模塊

//webUtils.js
export var e='export';
console.log(e) //export
  import {e} from './webUtils.js';
  console.log(e) //export

CommonJS

//utils.js
exports.e = 'export';
console.log(a) 
a = require('./utils');
console.log(a)

程序報(bào)錯(cuò)

ReferenceError: a is not defined

(5)import/export 只能在模塊頂層使用府瞄,不能在函數(shù)、判斷語句等代碼塊之中引用;require/exports 可以遵馆。

   import fs from  './webUtils.js';
   function a(){
    import {e1} from './webUtils.js';
    console.log(e1)
   }
   a();
   console.log(fs())

程序報(bào)錯(cuò)

Uncaught SyntaxError: Unexpected token '{'

前面提到過 import/export 在代碼靜態(tài)解析階段就會(huì)生成鲸郊,不會(huì)去分析代碼塊里面的 import/export,所以程序報(bào)語法錯(cuò)誤货邓,而不是運(yùn)行時(shí)錯(cuò)誤秆撮。

6. 是否采用嚴(yán)格模式

嚴(yán)格模式是采用具有限制性JavaScript變體的一種方式

import/export 導(dǎo)出的模塊默認(rèn)調(diào)用嚴(yán)格模式。

var fun=()=>{
    mistypedVaraible = 17; //報(bào)錯(cuò)换况,mistypedVaraible is not defined
};
export default fun;

require/exports 默認(rèn)不使用嚴(yán)格模式职辨,可以自定義是否使用嚴(yán)格模式。 例如

exports.fun = ()=>{
 mistypedVaraible = 17; //沒有調(diào)用嚴(yán)格模式戈二,不會(huì)報(bào)錯(cuò)
};

7. 其他模塊化方法

動(dòng)態(tài)導(dǎo)入 import()

import(modulePath) 表達(dá)式加載模塊并返回一個(gè) promise舒裤,該 promise resolve 為一個(gè)包含其所有導(dǎo)出的模塊對(duì)象。

我們可以在代碼中的任意位置動(dòng)態(tài)地使用它觉吭。例如:

import('/modules/my-module.js') //動(dòng)態(tài)導(dǎo)入
  .then((module) => {
    // Do something with the module.
});

建議: 請(qǐng)不要濫用動(dòng)態(tài)導(dǎo)入 import()(只有在必要情況下采用)腾供。靜態(tài)框架能更好的初始化依賴,而且更有利于靜態(tài)分析工具和 tree shaking 發(fā)揮作用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鲜滩,一起剝皮案震驚了整個(gè)濱河市伴鳖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌徙硅,老刑警劉巖榜聂,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嗓蘑,居然都是意外死亡须肆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門桩皿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來休吠,“玉大人,你說我怎么就攤上這事业簿×鼋福” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵梅尤,是天一觀的道長(zhǎng)柜思。 經(jīng)常有香客問我,道長(zhǎng)巷燥,這世上最難降的妖魔是什么赡盘? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮缰揪,結(jié)果婚禮上陨享,老公的妹妹穿的比我還像新娘葱淳。我一直安慰自己,他們只是感情好抛姑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布赞厕。 她就那樣靜靜地躺著,像睡著了一般定硝。 火紅的嫁衣襯著肌膚如雪皿桑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天蔬啡,我揣著相機(jī)與錄音诲侮,去河邊找鬼。 笑死箱蟆,一個(gè)胖子當(dāng)著我的面吹牛沟绪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播空猜,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼绽慈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了抄肖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤窖杀,失蹤者是張志新(化名)和其女友劉穎漓摩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體入客,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡管毙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了桌硫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夭咬。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖铆隘,靈堂內(nèi)的尸體忽然破棺而出卓舵,到底是詐尸還是另有隱情,我是刑警寧澤膀钠,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布掏湾,位于F島的核電站,受9級(jí)特大地震影響肿嘲,放射性物質(zhì)發(fā)生泄漏融击。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一雳窟、第九天 我趴在偏房一處隱蔽的房頂上張望尊浪。 院中可真熱鬧,春花似錦、人聲如沸拇涤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽工育。三九已至虾宇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間如绸,已是汗流浹背嘱朽。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怔接,地道東北人搪泳。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像扼脐,于是被迫代替她去往敵國(guó)和親岸军。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • require 和 import 分別是不同模塊化規(guī)范下引入模塊的語句瓦侮,下文將介紹這兩種方式的不同之處艰赞。 1.兩種...
    newTmorrow閱讀 247評(píng)論 0 0
  • 【轉(zhuǎn)】 遵循的模塊化規(guī)范不一樣 模塊化規(guī)范:即為 JavaScript 提供一種模塊編寫、模塊依賴和模塊運(yùn)行的方案...
    houruyaogeili閱讀 3,296評(píng)論 0 2
  • 當(dāng)前端應(yīng)用越來越復(fù)雜時(shí)肚吏,我們想要將代碼分割成不同的模塊方妖,便于復(fù)用、按需加載等罚攀。 require 和 import ...
    scarqin閱讀 844評(píng)論 0 2
  • 前言 這個(gè)問題也可以變?yōu)?commonjs模塊和ES6模塊的區(qū)別党觅; 先來一道面試題測(cè)驗(yàn)一下:下面代碼輸出什么 答案...
    IOneStar閱讀 710評(píng)論 0 2
  • 遵循的模塊化規(guī)范不一樣 模塊化規(guī)范:即為 JavaScript 提供一種模塊編寫炫掐、模塊依賴和模塊運(yùn)行的方案魁莉。誰讓最...
    shirley_ee84閱讀 175評(píng)論 0 0