js中關(guān)于require與import的區(qū)別及說明
require和import的區(qū)別
起源
es6誕生之前,js一直沒有模塊系統(tǒng),就連css都有@import,對(duì)現(xiàn)在復(fù)雜的大型項(xiàng)目開發(fā)無疑是一種阻礙。
es6在2015年6月正式發(fā)布,所以es6也有一個(gè)別稱es2015。官方?jīng)]有提出es6之前,社區(qū)給出了解決模塊問題的方案,那就是node.js。
介紹到這個(gè)地方,其實(shí)require和import的起源已經(jīng)出現(xiàn)了,es6中模塊解決方案使用的關(guān)鍵字是import,而node.js提供的解決方案使用的關(guān)鍵字是require。
node.js由Ryan Dahl在2009年發(fā)布。node.js提供的模塊化也叫CommonJS,不過node.js主要用于服務(wù)端的開發(fā),但是隨著時(shí)代的發(fā)展,現(xiàn)在的一些前端框架也依賴node.js
導(dǎo)出命令/引入命令
要想使用require或者import,首先得知道使用這兩種方式對(duì)應(yīng)的導(dǎo)出方式是怎樣的,從現(xiàn)在開始,下文分別以CommonJS和es6來區(qū)分兩種解決方案。
CommonJS
導(dǎo)出變量,方法,對(duì)象
// testcommonjs.js exports.a = 123; exports.b = 'hello'; exports.c = function(){ ? console.log('ccc') } exports.d = { ? foo: 'bar' } //等價(jià)=>? module.exports.a = 123; module.exports.b = 'hello'; //等價(jià)=>? module.exports = { ? a:123, ? b:'hello', ? c:function(){ ? ? console.log('ccc') ? }, ? d:{ ? ? foo:bar ? } }
建議使用module.exports,單獨(dú)使用exports在某些情況下會(huì)產(chǎn)生意想不到的錯(cuò)誤,這不是本文討論的重點(diǎn)
引入和使用
//index.js var test = require('./testcommonjs') console.log(test.a) console.log(test.b) test.c() console.log(test.d.foo)
es6
導(dǎo)出變量,方法,對(duì)象(這里只列舉常用的一些方法,具體的使用方法請(qǐng)參考阮一峰e(cuò)s6入門)
//testesmodule.js export var a = 123 export var b = 'hello' export function c(){ ? console.log('ccc') } export var d = { ? foo: 'bar' }
引入和使用
import { a,b,c,d } from './testesmodule' console.log(a) console.log(b) c() console.log(d.foo) //等價(jià)=>? import * as test form './testesmodule' console.log(test.a) console.log(test.b) test.c() console.log(test.d.foo)
靜態(tài)優(yōu)化
這是從阮一峰大神的文檔中學(xué)習(xí)到的一個(gè)概念。他在文檔中以node的核心模塊fs舉了一個(gè)例子
es6
// ES6模塊 import { stat, exists, readFile } from 'fs';
注:不要試圖在沒有配置babel的項(xiàng)目中去測(cè)試上面的代碼,因?yàn)閚ode到目前為止依然不支持es6的模塊化語法(筆者目前的node版本:v10.15.0),盡管它已經(jīng)實(shí)現(xiàn)了絕大部分的es6特性。
CommonJS
// CommonJS模塊 let { stat, exists, readFile } = require('fs');
這樣看起來,fs模塊的引入方式在es6中和CommonJS中似乎只是語法上的區(qū)別,但是實(shí)際上,在CommonJS中上述代碼的處理方式是這樣的
let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;
也就是說,為了使用fs中的stat、exists、readFile方法,在代碼執(zhí)行使必須把fs整個(gè)模塊全部加載進(jìn)來,生成一個(gè)對(duì)象_fs,然后再從這個(gè)對(duì)象上面讀取3個(gè)方法,這種加載被稱為“運(yùn)行時(shí)加載”,因?yàn)橹挥羞\(yùn)行時(shí)才能得到這個(gè)對(duì)象。
而es6模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量,從這個(gè)角度上來看,es6的模塊化效率要比CommonJS高得多。阮一峰大神在文檔中還列舉了一些靜態(tài)加載的其他優(yōu)點(diǎn),但是本菜鳥并不能看懂╮(╯▽╰)╭
新的思考:
fs是node.js的核心模塊,為什么es6的模塊化語法能夠生效,在ws中通過文件定位,發(fā)現(xiàn)node.js的核心模塊代碼全是用ts寫的,但是由于對(duì)ts語法不太熟悉,無法理解ts是如何能夠做到既兼容CommonJS又兼容es6的。
(com)require和import,動(dòng)態(tài)和靜態(tài)
require和import的區(qū)別問題
require用于讀取并執(zhí)行js文件, 并返回該模塊的exports對(duì)象, 若無指定模塊, 會(huì)報(bào)錯(cuò)。CommonJS規(guī)范加載模塊是同步且動(dòng)態(tài)的, 只有加載完成, 才能執(zhí)行后續(xù)操作??梢栽诖a中引入
import用于引入外部模塊, 其他腳本等的函數(shù), 對(duì)象或者基本類型。
import屬于ES6的命令, 它和require不一樣, 它會(huì)生成外部模塊的引用而不是加載模塊,等到真正使用到該模塊的時(shí)候才會(huì)去加載模塊中的值。
動(dòng)態(tài)引入和靜態(tài)引入
webpack支持node的commonJS標(biāo)準(zhǔn),而且它的require實(shí)現(xiàn)和node極為類似;所以將node的require和webpack的require放在一起講:
而且因?yàn)関ue用了webpack,所以在vue中webpack的require也可以使用;
require是動(dòng)態(tài)引入,因?yàn)樗沁\(yùn)行時(shí)調(diào)用,可以放在代碼的任何位置。
使用webpack的require需注意:
let url = "@/assets/images/carousel/logo.svg" require(url) ? ?//報(bào)錯(cuò) let url = "logo.svg" require("@/assets/images/carousel/"+url); //正確
不能直接給require變量,要給require一個(gè)初始的地址,具體的文件名給變量,以方便遍歷
而import支持靜態(tài)引入和動(dòng)態(tài)引入兩種:
1.靜態(tài)引入
import { a, b, c } from "./a";
2.動(dòng)態(tài)引入
if (condition) { ? import('moduleA').then(...); } else { ? import('moduleB').then(...); }
PS1:區(qū)分靜態(tài)和動(dòng)態(tài)
靜態(tài)是按照文件的嵌套關(guān)系找到文件或者分析代碼,不需要運(yùn)行
動(dòng)態(tài)與執(zhí)行順序有關(guān),會(huì)在執(zhí)行的過程中根據(jù)變化進(jìn)行一些操作
PS2:node中兩種導(dǎo)出方式的區(qū)別
1.置換exports整個(gè)對(duì)象
module.exports = {} ?? const lib = require("xxx")
2.不置換,只是編輯exports,加屬性,這個(gè)aaa就是key
exports.aaa === module.exports.aaa exports.aaa = 123 const {aaa} = require("xxx")
無論時(shí)哪種,最后返回的都是exports對(duì)象,都可以通過鍵值從里邊拿值
PS3:ES6中兩種導(dǎo)出方式的區(qū)別
1.export
export ? func1=()=>{} export ? func2=()=>{} import { func1, func2 } from 'xxx';
2.export default
export default class Example{} import Example from "xxx"
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于JavaScript實(shí)現(xiàn)點(diǎn)擊頁面任何位置返回
這篇文章主要介紹了基于JavaScript實(shí)現(xiàn)點(diǎn)擊頁面任何位置返回的實(shí)例代碼,需要的朋友可以參考下2016-08-08ion content 滾動(dòng)到底部會(huì)遮住一部分視圖的快速解決方法
本文給大家?guī)砹薸on content 滾動(dòng)到底部會(huì)遮住一部分視圖的快速解決方法,其實(shí)解決方法超簡單的,只要在你的controller里面預(yù)先注入$ionicScrollDelegate就可以了,感興趣的朋友通過本文一起學(xué)習(xí)吧2016-09-09表單元素值獲取方式j(luò)s及java方式的簡單實(shí)例
下面小編就為大家?guī)硪黄韱卧刂但@取方式j(luò)s及java方式的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10簡易 Javascript 調(diào)試包 Debug包
來看一個(gè)簡易的 Javascript 調(diào)試包 jscript.debug.js,包含兩個(gè)函數(shù)2010-10-10使用JS實(shí)現(xiàn)動(dòng)態(tài)時(shí)鐘
這篇文章主要為大家詳細(xì)介紹了使用JS實(shí)現(xiàn)動(dòng)態(tài)時(shí)鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03js利用FileReader實(shí)現(xiàn)圖片轉(zhuǎn)base64格式并上傳預(yù)覽頭像
本文主要介紹了js利用FileReader實(shí)現(xiàn)圖片轉(zhuǎn)base64格式并上傳預(yù)覽頭像,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05再談JavaScript中bind、call、apply三個(gè)方法的區(qū)別與使用方式
這篇文章主要介紹了Javascript中bind、call、apply三個(gè)方法的使用方式,需要的朋友可以參考下2022-05-05