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