ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript のモジュール化の簡単な分析

JavaScript のモジュール化の簡単な分析

高洛峰
高洛峰オリジナル
2017-02-04 16:24:581064ブラウズ

前書き

モジュール化に関して、最も直接的に現れるのは、私たちが書いたrequireキーワードとimportキーワードです。関連情報を確認すると、必ずCommonJSやCMD AMDなどの用語や、RequireJSやSeaJSなどの聞き慣れないフレームワークが登場します。たとえば、SeaJS の公式 Web サイトでは、SeaJS について次のように説明されています。「シンプルでフレンドリーなモジュール定義仕様、Sea.js は CMD 仕様に従っています。自然で直感的なコード編成、依存関係の自動読み込み...」

フロントエンドとして初心者、申し訳ありませんが、理解できません。私のいつものスタイルでは、何かを紹介する前に、それがなぜ必要なのかを必ず説明する必要があります。

JavaScriptの基礎

クライアント側で作業する学生は、OCの#import "classname"、Swiftのモジュールとファイル修飾子、Javaのインポートパッケージ+クラスモードに精通している必要があります。私たちは、ファイルの参照がクラスを参照するというパターンに慣れています。ただし、JavaScript のような動的言語では、状況が変わります。例:







< p id="hello"> こんにちはワールド




< ;/ html>
//index.js
function onPress() {
var p = document.getElementById('hello');
p.innerHTML = add(1, 2);
}

このようにして見ることができますindex.js は他の JS ファイルの内容を制御できません。add メソッドを呼び出せるかどうかは、独自の HTML ファイルが他の JS ファイルを正しく参照しているかどうかによって決まります。

予備的なモジュール化

先ほど述べた問題点は、実際には 2 つのタイプに分類できます:

index.js はインポートできず、HTML 参照に依存します

index.js は add メソッドのソースを区別できず、名前空間がありません

の概念 最初の質問は後で答えます。たとえば、最初に関数をオブジェクトに入れて、ユーザーがこのオブジェクトの複数のメソッドを呼び出せるようにします。 //index.js

function onPress() {

var p = document.getElementById('hello');

p.innerHTML = math.add(1, 2);
}

//math.js
var math = {
base: 0,
add: function(a, b) {
return a + b +base;
},
};


Index.js 名前空間で簡易版を指定できることがわかります(つまり数学です)。ただし、小さな問題がまだあります。たとえば、base 属性は外部に公開され、変更される可能性もあります。したがって、より良い方法は、クロージャ内で math を定義して内部プロパティを非表示にすることです。 ) {
return a + b + base;

},

};

})();


ここまででモジュールの定義と利用を実装しました。ただし、モジュール化の本質の 1 つは名前空間にあります。つまり、数学モジュールはグローバルではなく、オンデマンドでインポートされることを望んでいます。この方法では、複数のファイルが同じ名前のオブジェクトを公開している場合でも、何も存在しません。問題。 Node.js と同様に、公開する必要があるモジュールは独自のエクスポート コンテンツを定義し、呼び出し元は require メソッドを使用します。

実際には、node.js の動作モードを単純にシミュレートし、中間層を追加することで解決できます。 まず、グローバル変数を定義します:

// global.js
var module = {
exports: {}, / / used 公開されたコンテンツをすべて保存します
};

次に、オブジェクトを math.js に公開します:

var math = (function() {
varbase = 0;
return {
add: function(a, b) {
return a + b + Base;
},
};
})();

module.exports.math = math;

ユーザーのindex.jsは、

var math = module.exportsとなるはずです。 math;

function onPress() {
var p = document.getElementById('hello');
// math
p.innerHTML = math.add(1, 2);
}

既存のモジュラー ソリューション

上記の単純なモジュール方式のアプローチには、いくつかの小さな問題があります。まず、index.js は math.js の実行に厳密に依存する必要があります。これは、math.js が実行された後でのみ、index.js 自体がグローバル module.export に登録されるためです。これには、開発者が js ファイルの読み込み順序を手動で管理する必要があります。プロジェクトが大きくなるにつれて、依存関係の維持はますます複雑になります。

第二に、JSファイルをロードするときにブラウザはWebページのレンダリングを停止するため、JSファイルの非同期オンデマンドロードも必要です。

最後の問題は、前に示した単純化されたモジュール化ソリューションではモジュールの名前空間が解決されないことです。同じエクスポートによって以前のコンテンツが置き換えられるため、解決策は「ファイル パス<–> エクスポート コンテンツ」テーブルを維持してロードすることです。ファイルパスに基づいて決定されます。

上記のニーズに基づいて、モジュール式ソリューションの多くのセットが市場に登場しています。なぜ複数の標準が存在するのかというと、実はフロントエンドの特性が原因です。統一された規格がないため、前述のexportやrequireなどのことを行う際に、誰もが規約に頼ってしまうケースが多くあります。コードの提供者がエクスポート内容を module.exports に格納し、ユーザーが module.export を読み込んだとしても、当然のことながら無駄になります。それだけでなく、各仕様の実装方法や使用シナリオも異なります。

CommonJS

よく知られた仕様としては、CommonJS、AMD、CMDなどがあります。有名なフレームワーク Node.js、RequireJS、Seajs はそれぞれ上記の仕様を実装しています。

最も古い仕様はNode.jsで使われるCommonJSです。この仕様は、JS スクリプトを同期的にロードするという以前のアプローチに似ています。ファイルはディスクに保存されるため、サーバー側でこれを実行しても問題はありません。ただし、ブラウザの特性により、JS スクリプトを非同期で読み込む必要があると判断されます。そうしないと応答が失われるため、CommonJS の仕様では実行できません。ブラウザで直接使用できます。

AMD

ブラウザ側の有名なモジュール管理ツールRequire.jsは、WebworkerのimportScripts(url)関数を介してJSスクリプトを読み込み、元々登録されていたコールバックを実行します。 Require.js は次のように記述されます:

require(['myModule1', 'myModule2'], function (m1, m2){
// メインコールバックロジック
m1.printName();
m2.printName();
} );

これら 2 つのモジュールは非同期でダウンロードされるため、どのモジュールが最初にダウンロードされて実行されるかは定かではありませんが、すべての依存関係が読み込まれた後にメイン コールバックが実行されることは確かです。

この Require.js の書き方はフロントローディングとも呼ばれます。メインロジックを書く前にすべての依存関係を指定する必要があり、これらの依存関係はすぐに非同期で読み込まれます。

Require.jsから派生した仕様はAMD(Asynchronous Module Definition)と呼ばれます。

CMD

もう一つの優れたモジュール管理ツールは Sea.js で、その記述方法は次のとおりです:

define(function(require,exports, module) {
var foo = require('foo'); // 同期
foo. add(1, 2);
...
require.async('math', function(math) { // 非同期
math.add(1, 2);
});
});

海.js は近くの読み込みとも呼ばれ、その書き方から Require.js との違いがよくわかります。依存関係を使用する必要がある場合にのみ、依存関係を宣言できます。

Sea.js は依存関係に遭遇すると、JS ファイルをダウンロードするだけで実行はしません。代わりに、依存するすべての JS スクリプトがダウンロードされるまで待機してから、メイン ロジックを最初から実行します。したがって、依存モジュールの実行順序は書き込み順序とまったく同じになります。

Sea.jsから派生した仕様はCMD(Common Module Definition)と呼ばれます。

ES 6のモジュール性

ES6では、モジュールをエクスポートするにはexportキーワードを使用し、モジュールを参照するにはimportキーワードを使用します。 ES 6 のこの標準セットは現在の標準とは直接関係がなく、現時点ではこれを直接サポートできる JS エンジンはほとんどないことに注意してください。したがって、Babel が実際に行うことは、サポートされていないインポートを現在サポートされている require に変換することです。

現時点では import と require の使用にほとんど違いはありませんが (本質的に同じものです)、JS エンジンが ES 6 import キーワードを解析できるようになると、実装全体が同じになるため、import キーワードを使用することを強くお勧めします。現在のように比較的大きな変化です。今すぐ import キーワードの使用を開始すると、将来のコードの変更は非常に小さくなります。

経由: http://fullstack.blog/2017/01/25/JavaScript%20%E6%A8%A1%E5%9D%97%E5%8C%96%E7%AE%80%E8%BF% B0/

JavaScript のモジュール化分析に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。