1. 程式人生 > >node裡面的模組 和 es6裡面的模組引入方式

node裡面的模組 和 es6裡面的模組引入方式

出處:https://blog.csdn.net/arsaycode/article/details/78959780

node: module.exports和require

es6:export和import

node:

該模組實現方案主要包含 require 與 module 這兩個關鍵字,其允許某個模組對外暴露部分介面並且由其他模組匯入使用。

//sayModule.js
function SayModule () {
    this.hello = function () {
        console.log('hello');
    };

    this.goodbye = function () 
{ console.log('goodbye'); }; } module.exports = SayModule; //main.js 引入sayModule.js var Say = require('./sayModule.js'); var sayer = new Say(); sayer.hello(); //hello

作為一個伺服器端的解決方案,CommonJS 需要一個相容的指令碼載入器作為前提條件。該指令碼載入器必須支援名為 require 和 module.exports 的函式,它們將模組相互匯入匯出。

ES6模組(module)

模組Module

一個模組,就是一個對其他模組暴露自己的屬性或者方法的檔案。

匯出Export

作為一個模組,它可以選擇性地給其他模組暴露(提供)自己的屬性和方法,供其他模組使用。

// profile.js
export var firstName = 'qiqi';
export var lastName = 'haobenben';
export var year = 1992;

//等價於

var firstName = 'qiqi';
var lastName = 'haobenben';
var year = 1992;
export {firstName, lastName, year}

1、 通常情況下,export輸出的變數就是本來的名字,但是可以使用as關鍵字重新命名。

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

//上面程式碼使用as關鍵字,重新命名了函式v1v2的對外介面。重新命名後,v2可以用不同的名字輸出兩次。

2、 需要特別注意的是,export命令規定的是對外的介面,必須與模組內部的變數建立一一對應關係。

// 報錯
export 1;

// 報錯
var m = 1;
export m;

//上面兩種寫法都會報錯,因為沒有提供對外的介面。第一種寫法直接輸出1,第二種寫法通過變數m,還是直接輸出1。1只是一個值,不是介面。

/ 寫法一
export var m = 1;

// 寫法二
var m = 1;
export {m};

// 寫法三
var n = 1;
export {n as m};

//上面三種寫法都是正確的,規定了對外的介面m。其他指令碼可以通過這個介面,取到值1。它們的實質是,在介面名與模組內部變數之間,建立了一一對應的關係。

匯入import

作為一個模組,可以根據需要,引入其他模組的提供的屬性或者方法,供自己模組使用。

1、 import命令接受一對大括號,裡面指定要從其他模組匯入的變數名。大括號裡面的變數名,必須與被匯入模組(profile.js)對外介面的名稱相同。如果想為輸入的變數重新取一個名字,import命令要使用as關鍵字,將輸入的變數重新命名。

import { lastName as surename } from './profile';

2、import後面的from指定模組檔案的位置,可以是相對路徑,也可以是絕對路徑,.js路徑可以省略。如果只是模組名,不帶有路徑,那麼必須有配置檔案,告訴 JavaScript 引擎該模組的位置。

3、注意,import命令具有提升效果,會提升到整個模組的頭部,首先執行。

foo();

import { foo } from 'my_module';

//上面的程式碼不會報錯,因為import的執行早於foo的呼叫。這種行為的本質是,import命令是編譯階段執行的,在程式碼執行之前。

4、由於import是靜態執行,所以不能使用表示式和變數,這些只有在執行時才能得到結果的語法結構。

/ 報錯
import { 'f' + 'oo' } from 'my_module';

// 報錯
let module = 'my_module';
import { foo } from module;

// 報錯
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}

5、最後,import語句會執行所載入的模組,因此可以有下面的寫法。

import 'lodash';
//上面程式碼僅僅執行lodash模組,但是不輸入任何值。

預設匯出(export default)

每個模組支援我們匯出一個沒有名字的變數,使用關鍵語句export default來實現.

export default function(){
            console.log("I am default Fn");
        }
//使用export default關鍵字對外匯出一個匿名函式,匯入這個模組的時候,可以為這個匿名函式取任意的名字

//取任意名字均可
import sayDefault from "./module-B.js";
sayDefault();
//結果:I am default Fn

1、預設輸出和正常輸出的比較

// 第一組
export default function diff() { // 輸出
  // ...
}

import diff from 'diff'; // 輸入

// 第二組
export function diff() { // 輸出
  // ...
};

import {diff} from 'diff'; // 輸入

//上面程式碼的兩組寫法,第一組是使用export default時,對應的import語句不需要使用大括號;第二組是不使用export default時,對應的import語句需要使用大括號。
export default命令用於指定模組的預設輸出。顯然,一個模組只能有一個預設輸出,因此export default命令只能使用一次。所以,import命令後面才不用加大括號,因為只可能對應一個方法。

2、因為export default本質是將該命令後面的值,賦給default變數以後再預設,所以直接將一個值寫在export default之後。

/ 正確
export default 42;

// 報錯
export 42;

//上面程式碼中,後一句報錯是因為沒有指定對外的介面,而前一句指定外對介面為default。

3、如果想在一條import語句中,同時輸入預設方法和其他變數,可以寫成下面這樣。

import _, { each } from 'lodash';

//對應上面程式碼的export語句如下
export default function (){
    //...
}
export function each (obj, iterator, context){
    //...
}

export 與 import 的複合寫法

如果在一個模組之中,先輸入後輸出同一個模組,import語句可以與export語句寫在一起。

export { foo, bar } from 'my_module';

// 等同於
import { foo, bar } from 'my_module';
export { foo, bar };

/ 介面改名
export { foo as myFoo } from 'my_module';

// 整體輸出
export * from 'my_module';
注意事項 
1、宣告的變數,對外都是隻讀的。但是匯出的是物件型別的值,就可修改。 
2、匯入不存在的變數,值為undefined。

ES6 中的迴圈引用

ES6 中,imports 是 exprts 的只讀檢視,直白一點就是,imports 都指向 exports 原本的資料,比如:

//------ lib.js ------
export let counter = 3;
export function incCounter() {
    counter++;
}

//------ main.js ------
import { counter, incCounter } from './lib';

// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4

// The imported value can’t be changed
counter++; // TypeError

因此在 ES6 中處理迴圈引用特別簡單,看下面這段程式碼:

//------ a.js ------
import {bar} from 'b'; // (1)
export function foo() {
  bar(); // (2)
}

//------ b.js ------
import {foo} from 'a'; // (3)
export function bar() {
  if (Math.random()) {
    foo(); // (4)
  }
}

假設先載入模組 a,在模組 a 載入完成之後,bar 間接性地指向的是模組 b 中的 bar。無論是載入完成的 imports 還是未完成的 imports,imports 和 exports 之間都有一個間接的聯絡,所以總是可以正常工作。

例項

//---module-B.js檔案---
//匯出變數:name
export var name = "cfangxu";

moduleA模組程式碼:
//匯入 模組B的屬性 name    
import { name } from "./module-B.js";   
console.log(name)
//列印結果:cfangxu

批量匯出

//屬性name
var name = "cfangxu";
//屬性age
var age  = 26;
//方法 say
var say = function(){
            console.log("say hello");
         }
//批量匯出
export {name,age,say}

批量匯入

//匯入 模組B的屬性
import { name,age,say } from "./module-B.js";
console.log(name)
//列印結果:cfangxu
console.log(age)
//列印結果:26
say()
//列印結果:say hello

重新命名匯入變數

import {name as myName} from './module-B.js';
console.log(myName) //cfangxu

整體匯入

/使用*實現整體匯入
import * as obj from "./module-B.js";

console.log(obj.name)
//結果:"cfangxu"
console.log(obj.age)
//結果:26
obj.say();
//結果:say hello