require和import的區別是什麼?看這個你就懂了

require import
動態評估 靜態評估
再運行時報錯 再解析時報錯
不是關鍵詞 是關鍵詞

語法

CommonJs

dep.jsnode

module.exports = {
    foo: function () {},
    bar: 'a'
}

app.js緩存

var dep = require('dep')
console.log(dep.bar)
dep.foo()

ESM

dep.jsapp

export foo function(){}
export const bar = 'a'

app.js模塊化

import { foo, bar } from 'dep'
console.log(bar)
foo()

加載方式的不一樣

使用require的時候,其實會將module的代碼進行包裝,變成以下樣子的代碼:ui

function (exports, require, module, __filename, __dirname) {
  const m = 1;
  module.exports.m = m;
}

而後在執行這個方法的時候,咱們能夠傳入:lua

const module = { exports: {} }
const require = function(){/* ...some module load code here */}
// __filename, __dirname是require的時候提供的路徑分析出來的
fun(module.exports, require, module, __filename, __dirname)

執行完成以後,就能經過module拿到方法中向外拋出的變量了。code

因此咱們能夠看到,module、require、exports都不是全局變量,而是專門爲這個模塊使用的局部變量。內存

require的時候真正作的事情以下:io

  1. Resolution / 解析路徑
  2. Loading / 加載代碼
  3. Wrapping / 包裝
  4. Evaluation / 評估執行
  5. Caching / 緩存

簡單來講就是根據require調用時傳入的路徑,首先要拿到真正的絕對路徑(是相對目錄的,仍是node_modules下面的等等),而後讀入代碼,包裝成上面顯示的樣子,而後傳給vm進行評估執行,獲得結果,最後進行緩存。console

因此,在模塊代碼執行完以前,node根本不知道這個模塊到底export出了什麼東西,這也是和ESM最大的區別,由於ESM是基於關鍵字的模塊化,是能夠在解析的過程當中就知道導出了什麼。

在解析ESM模塊的時候,在把代碼傳給VM執行以前,就能夠獲得一個叫作Module Record的內部結構,他保存了模塊倒出的內容的列表,在你import {f} from f的時候,他其實在你引用的地方和倒出的地方的f之間創建了鏈接,即它們是指向同一內存的,即使是原始數據類型,你修改模塊中的指也會致使引用處的變化。啥意思呢?

// dep.js
export let a = 1
setTimeout(() => a += 1, 500)

// app.js
import { a } from 'dep'
setTimeout(function () {
  console.log(a)
}, 1000)

輸出的會是2,可是你用require,CommonJs模塊來作,就會是1,由於CommonJs是普通的值傳遞或者引用傳遞

這就是require和import最大的區別

相關文章
相關標籤/搜索