blog

ES6モジュールとCommonJSの比較

I. ES6Module モジュール関数は、主に export と import の 2 つのコマンドで構成されます。export はモジュールの外部インターフェイスを指定するために使用され、impo...

Oct 22, 2020 · 6 min. read
シェア

ES6 Module 

モジュールの機能はexportとimportの2つのコマンドで構成されています。 exportコマンドはモジュールの外部インターフェースを指定するために使用され、importコマンドは他のモジュールが提供する機能を入力するために使用されます。

importとexportコマンドは、コードブロック内ではなく、モジュールのトップレベルでしか使えません。

モジュール:モジュールは独立したファイルです。ファイル内の変数はすべて外部からは利用できません。外部からモジュール内部の変数やメソッドにアクセスする必要がある場合は、export キーワードを使用して変数やメソッドをエクスポートする必要があります。

輸出輸出:

エクスポートされるのは参照で、ポインタに似ており、メモリ上の値を指し示します。

// demo.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
var getName = function() {
 return firstName + lastName;
}
export {firstName, lastName, year, getName };
//上のファイルはES6ではモジュールとして扱われ、exportコマンドを使って3つの変数と関数を外部にエクスポートしている。
//さらに、export文が出力するインターフェースは、対応する値に動的にバインドされる。,
//つまり、このインターフェースを通じて、モジュール内部のリアルタイムの値をフェッチすることができる。// 最後に、エクスポート/インポート・コマンドはブロック・レベル・スコープに置くことはできず、グローバル・スコープ内の任意の場所に置くことができる。

輸入輸入:

静的インポート:

// main.js import {firstName, lastName, year} from './profile.js'; function setName(element) { element.textContent = firstName + ' ' + lastName; } //上のコードのimportコマンドは、プロファイルをロードするために使われている。.jsファイルから変数がインポートされる。 //importこのコマンドは、他のモジュールからインポートする変数名を指定する中括弧のペアを受け付ける。 //中括弧内の変数名は、インポートされるモジュール(プロファイル)名と同じでなければならない。.js)外部インターフェースの名前は同じである。 //全体としてインポートする import * as myModule from './my-module.js';//括弧を追加する必要はない{} //my-moduleからエクスポートされる変数/関数は以下の通りである。, //オブジェクトmyModuleにプロパティ/メソッドとして入力する。 //myModuleで.プロパティ名 /myModule.を呼び出すメソッド import './lodash.js';//lodashモジュールをすぐに実行する。 //エクスポート/インポートのデフォルト:ユーザーは、テンプレート/エクスポートのデフォルト構文で変数名や関数名を最初に知る必要はない。 //これはデフォルトの出力なので、テンプレートは一度しか使用できない。 export default function foo() { console.log('foo'); } //デフォルトのインポート import customName from './default.js';//括弧を追加する必要はない{} customName(); // 'foo'

動的インポート: import()

import()関数は、モジュールだけでなく、モジュール以外のスクリプトでも、どこでも使うことができます。実行時実行なので、この文が実行されたときだけ、指定されたモジュールがロードされます。

さらに、import()関数はロードされたモジュールと静的な接続を持ちません。

import("モジュール・パス") //ES6 import()Promiseオブジェクトを返す import(`./section-modules/${someVariable}.js`).then(module => { module.loadPageInto(main); }).catch(err => { main.textContent = err.message; }); //import()モジュールが正常にロードされると、モジュールはオブジェクトとしてthenメソッドのパラメータとして使用される。 //したがって、オブジェクト分解代入の構文を使用して、出力インターフェースを得ることができる。 import('./myModule.js').then(({export1, export2}) => {// export1, export2myModuleからのデリゲート.jsのエクスポートされた出力インターフェイスは}); //モジュールにデフォルトの出力インターフェイスがある場合は、パラメータで直接取得できる。/---モジュール.js export default function(){ return test; } /---test.js import('./myModule.js').then((myModule)=>{ console.log(myModule.default) //関数を取得する }); //次のように書くこともできる。 import('./myModule.js').then(({defaultmyModuleDefault})=>{ console.log(myModuleDefault) //関数を取得する});

注:import()はNodeのrequire()メソッドに似ていますが、前者は非同期ロード、後者は同期ロードという違いがあります。

適用される機会:

ロードオンデマンド

import() は必要なときにモジュールをリロードします。

条件付きローディング

import()をifブロックの中に置くことで、状況に応じて異なるモジュールをロードすることができます。

if (condition) {
 import('moduleA').then(...);
} else {
 import('moduleB').then(...);
}

動的モジュールパス

import() により、モジュールのパスを動的に生成することができます。

import(f()).then(...); //f関数の結果に応じて、異なるモジュールがロードされる。

CommonJSモジュールの仕様

CommonJSには、モジュールに関する3つの仕様があります。

1.モジュールの定義 モジュール、エクスポート

CommonJSのモジュールは、module.exportsオブジェクトというたった1つのユニークなエクスポートを持つだけなので、エクスポートしたい変数や関数をすべてこのオブジェクトに入れ、オブジェクトをエクスポートします。エクスポートされるすべての変数と関数は、このオブジェクトに入れられ、エクスポートされます。 これらの変数と関数は、外部からアクセスできるようになり、エクスポートされないものは、外部からは見えなくなります。

/---index.js
function isNumber (n) {
 return typeof n === 'number'
}
module.exports = {
 sum: function(a, b) {
 return a+b;
 }
}
/----/
var mod = require('./index')
console.log(mod.sum(2, 2)) // 4
mod.isNumber() // エラーを投げる

注:フォームのエクスポートmodule.exports = {}、 またフォームのエクスポートexports.a = 'blabla'

しかし、決してexports = {}として エクスポートしてはいけません。

最後にエクスポートされるのはmodule.exportsであり、exportsオブジェクトではありません。

2. モジュールへのリファレンス

**require メソッドは、モジュール内でエクスポートされた module.exports オブジェクトを返します。

**

3.モジュールの識別

モジュールの識別には主にいくつかの種類があります。

1. "小さなこぶ "命名法に準拠した文字列。

2. または'...' 相対パスモジュール

3.絶対パス

一つ細かい点を挙げるとすれば

**その他:** NodeのCommonJSの実装は3つのポイントに分けられます。

1. モジュールパス解析:入力されたパラメータを解析し、このモジュールが以下のどのカテゴリに属するかを判断します:

  • コアモジュール
  • パス・モジュール
  • カスタム・モジュール

2. モジュールロケータ:結果のモジュールのファイル名です。

ファイル名の決定には以下が使用されます。

  • 最初のステップでは、ディレクトリ内のpackage.jsonを見つけ、JSON.parse()を使用してメインフィールドを解析します。
  • 2番目のステップでは、メイン・フィールドで指定されたファイルがまだ拡張子を省略している場合、.js、.node、.jsonが順番に追加されます。
  • 第三に、mainフィールドで指定されたファイルが存在しない場合、またはpackage.jsonが全く存在しない場合は、このディレクトリにあるindex.js、index.node、index.jsonファイルがデフォルトで読み込まれます。

3.**モジュールのコンパイル:** Nodeは新しいモジュールオブジェクトを作成し、パスに従ってロードとコンパイルを行います。ファイル拡張子が異なる場合、ロード方法は以下のように異なります。

  • jsファイル - コンパイルされ、fsモジュール経由で同期的にファイルを読み込んだ後に実行されます。
  • ノード・ファイル - これはC/C++で書かれた拡張ファイルで、最終コンパイルで生成されたファイルをdlopen()メソッドでロードします。
  • jsonファイル - fsモジュールを通して同期的にファイルを読み込み、JSON.parse()を使って返された結果をパースします。
  • 残りの拡張ファイルは、.jsファイルとして読み込まれます!

正常にコンパイルされた各モジュールは、二次導入のパフォーマンスを向上させるために、Module._cacheオブジェクトのインデックスとしてファイルパスをキャッシュします。

ES6 ModuleCommonJSとの違い

1、ES6モジュールコンパイル時出力インターフェース、CommonJSランタイムローディング

2、インポートされたES6モジュールは、モジュールへの参照は、読み取り専用で、その内部の状態を変更することはできませんが、内部の値の変更は、外部使用の値に影響を与える、つまり、モジュールの元の値は、ロードされた値を変更することも変更されます。

3、CommonJSのインポートは、モジュールの変数や関数の値である、つまり、元のモジュールの値の変更は、値が浅いコピーと同様に、ロードされている影響を与えません。

4, CommonJSの this は現在のモジュールを指し、ES6の thisは未定義を指します

CommonJsのモジュール性

// lib.js
var counter = 3;
function incCounter() {
 counter++;
}
module.exports = { 
counter: counter, 
incCounter: incCounter
};
// main.js
var mod = require('./lib'); 
console.log(mod.counter); // 3
mod.incCounter();
console.log(mod.counter); // 3

ES6 モジュラー

// lib.js export let counter = 3; export function incCounter() { counter++; } // main.js import { counter, incCounter } from './lib'; console.log(counter); // 3 incCounter(); console.log(counter); //4

注: CommonJSは、スクリプトの実行後にのみ生成されるオブジェクトをロードします。ES6モジュールはオブジェクトではありません。その外部インターフェイスは、コードの静的解析段階で生成される静的定義にすぎません。

Read next

イーサネット技術はどのようにセキュリティを提供するか

ビーコンチェーンを理解するには、まずイーサ2.0の中核機能であるシャーディング技術を理解してください。チェーンはビーコンチェーンとは別のもので、フェーズ1でのみ導入が予定されている機能です。しかし、まずこの機能を理解することで、Ether 2.0の全体的な技術アーキテクチャとその設計内容を理解することができます。イーサネット1.0では、システムによって処理される1秒あたりのトランザクション数が多く...

Oct 22, 2020 · 2 min read