require('./expample.js).default詳解


最近總碰到類似於

var a = require('./expample.js).default

 

這樣的代碼,感覺很奇葩,總結一波。

為什么會出現這個問題?

import 是靜態編譯的,而 require 可以動態加載,也就是說你可以通過判斷條件來決定什么時候去 require ,而 import 則不行,所以有時候我們會面臨需要通過require 去導入一個es6模塊(比如react-hot-loader官方demo :P)

當然,這只是場景之一。

前置知識

  1. ES6 Module常用語法。譬如export導出模塊接口 | import 倒入模塊| export default語法糖
  2. Node.js模塊常用。譬如module.exports | require
  3. ES6模塊與commonjs模塊的區別(靜態編譯與動態加載 | 值得引用與值的拷貝)

如果上述前置知識您有所不了解的話,建議拜讀一下阮一峰老師的《ECMAScript 6 入門》一書中的兩個章節:

  1. Module 的語法
  2. Module 的加載實現

如果您已經具備了上述知識,我們來討論一下

  1. export default為什么是語法糖
  2. require一個ES6 Module

export default為什么是語法糖

default關鍵字 說白了,就是別名(as)的語法糖

以下代碼應當是非常常見的:

導出接口

// a.js
function a(){}
export {a}

 

導入模塊

// b.js
import {a} from './a'

 

花括號就是解構賦值的語法,我們可以理解為export導出了一個對象,對象里存在a這個函數,就像下面這樣

{
  a:function(){}
}

 

於是就有了后面的通過結構賦值取出a,所以變量名必須一致。

ECMAScript 6 入門:從前面的例子可以看出,使用import命令的時候,用戶需要知道所要加載的變量名或函數名,否則無法加載。但是,用戶肯定希望快速上手,未必願意閱讀文檔,去了解模塊有哪些屬性和方法。
為了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default命令,為模塊指定默認輸出。

default可以理解為這一語法的語法糖

導出接口

// d.js
export default function() {}

// 等效於:
function a() {};
export {a as default};

 

導入模塊

import a from './d';

// 等效於,或者說就是下面這種寫法的簡寫,是同一個意思
import {default as a} from './d';

 

這個語法糖的好處就是import的時候,可以省去花括號{}。

簡單的說,如果import的時候,你發現某個變量沒有花括號括起來(沒有*號),那么你在腦海中應該把它還原成有花括號的as語法。

本質上依舊是結構賦值呀,只不過我們寫的更為簡便,假裝花括號消失了罷了。

如何require一個ES6 Module

stackoverflow上有一個針對本文題目比較好的回答,原文如下:

Finally, the require and require.default... when dealing with ES6 imports (export default MyComponent), the exported module is of the format {"default" : MyComponent}. The import statement correctly handles this assignment for you, however, you have to do the require("./mycomponent").default conversion yourself. The HMR interface code cannot use import as it doesn't work inline. If you want to avoid that, use module.exports instead of export default.

我來翻譯下原文

最后,require和require.default...當在node中處理ES6 模塊(export default mycomponent)導入的時候,導出的模塊格式為

{
  "default": mycomponent
}

import
語句正確地為你處理了這個問題,然而你必須自己執行 require("./mycomponent").default. HMR(熱更新模塊)不在 inline 模式工作的情況下,接口代碼不能使用 import ,如果你想避免,使用module.exports而不是export default;

上文提到過,export 關鍵字是導出一個對象,對象內存在一個屬性(我們要暴露的),export default 則是 export 語法糖,import 一個export default 暴露出來的模塊包含了解構賦值的步驟,所以在node中使用require去請求一個export default的模塊需要我們通過.語法去取出對象中的屬性(因為require木有解構賦值),清晰明了。

換個說法,如果 require 的 commonjs規范的模塊,即:
導出:

// a.js
module.exports = {
  a:'helloworld'
}

 

導入:

// b.js
var m = require('./a.js');
console.log(m.a); // helloworld

 

這樣就顯得非常清晰,我們 module.exports 的是啥,require 的就是啥。

但export default包裝了一層語法糖,讓我們看得不甚清晰:

const a = 'helloworld';
export default a;

其實導出的是

{
  "default": a
}

 

而並非 a 這個變量,這就是我為什么之前要強調語法糖了,如果你將 export default 還原為:

const a = 'helloworld';
export {a as default}

 

是不是就能清楚一點了呢。

我們的疑問也就迎刃而解了。

注:以上所有代碼都是在webpack開發環境(babel)中運行(保證ES6模塊語法可以被識別)。

參考:Node中沒搞明白require和import,你會被坑的很慘

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM