私は JS についてあまり知識がなかったのですが、最近この問題に遭遇したので、まだ完全に理解できていないので、最初にメモを投稿します。
第 1 章 JavaScript モジュラー プログラミング(1): モジュールの書き方
1 原文
// モジュールは、特定の関数を実装するためのメソッドのセットです。さまざまな関数 (およびステータスを記録する変数) が単純にまとめられている限り、それはモジュールです。
関数 m1(){
// ...
}
関数 m2(){
// ...
}
// 上記の関数 m1() と m2() は、使用時に直接呼び出すだけでモジュールを形成します。
// 欠点: 「汚染された」グローバル変数。変数名が他のモジュールと競合しないという保証はなく、モジュールのメンバー間に直接の関係はありません。
2 オブジェクトの書き込み方法
// 把模块写成一个对象,所有的模块成员都放到这个对象里面; var module = new Object({ _count:0, m1:function(){ // ... }, m2:function(){ // ... } }); // 上面的函数m1()和m2(),都封装在module对象里;使用时直接调用这个对象的属性; module.m1(); // 但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写; module._count = 4;
var module = (function(){ var _count = 0; var m1 = function(){ // ... }; var m2 = function(){ }; return { m1:m1, m2:m2 }; })(); // 使用上面的写法,外部代码无法读取内部的_count变量; console.info(module._count); // undefined; // 上面的写法就是JavaScript模块的基本写法;
// 如果模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"; var module = (function(mod){ mod.m3 = function(){ // ... }; return mod; })(module); // 上面的代码为module模块添加了一个新方法m3(),然后返回新的module模块;
// 在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载; // 如果采用上一节的写法,第一个执行的部分有可能加载一个不存在的空对象,这时就要采用"宽放大模式"; var module = (function(mod){ // ... return mod; })(window.module || {}); // 与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象;
第 2 章 JavaScript モジュラー プログラミング (2): AMD 仕様
1 モジュール仕様
// 現在、一般的な JavaScript モジュール仕様は CommonJS と AMD の 2 つです。
2 CommonJS
// node.js はサーバーサイド プログラミングに JavaScript 言語を使用します。これにより、「JavaScript モジュラー プログラミング」が正式に誕生しました。
// node.js のモジュール システムは CommonJS 仕様を参照して実装されています
CommonJS には、モジュールをロードするためのグローバル メソッド require() があります。
var math = require('math'); var math = require('math'); // モジュールをロードします。
Math.add(2,3); // モジュールのメソッドを呼び出します =>5;
3 ブラウザ環境
var math = require('math');
Math.add(2,3);
// 問題: math.add(2,3);
の前に、require('math') で math.js がロードされるまで待つ必要があります。
// したがって、ブラウザモジュールは「同期読み込み」を使用できず、「非同期読み込み」のみを使用できます;==>AMD;
4 つの AMD
// モジュールの非同期ロードを使用します。モジュールのロードは、後続のステートメントの実行に影響しません。このモジュールに依存するすべてのステートメントは、コールバック関数
で定義されます。
// このコールバック関数は読み込みが完了するまで実行されません
// AMD もモジュールをロードするために require() ステートメントを使用しますが、次の 2 つのパラメータが必要です:
require([モジュール],コールバック);
// module: は配列であり、内部のメンバーはロードされるモジュールです。
// callback: ロードが成功した後のコールバック関数です。
require(['math'],function(math){
Math.add(2,3);
});
// math.add() と math モジュールの読み込みは同期されないため、ブラウザはフリーズしません。したがって、AMD はブラウザ環境に適しています。
第 3 章 JavaScript モジュラープログラミング (3): require.js の使用法
1. require.js
を使用する理由
// 複数の js ファイルを順番にロードする必要があります;
// 1. ロードするファイルが増えると、ブラウザは Web ページのレンダリングを停止します。
// 2. js ファイル間の依存関係により、読み込み順序を厳密に保証する必要があります。依存関係が複雑になると、コードの記述とメンテナンスが困難になります。
// したがって、require.js は次の 2 つの問題を解決します:
// 1. Web ページの応答が失われないように、js ファイルの非同期読み込みを実装します。
// 2. コードの作成とメンテナンスを容易にするためにモジュール間の依存関係を管理します。
2 require.js の読み込み
1. require.js をロードします
も記述します。
2. main.jsをロードします
// data-main 属性の機能は、Web プログラムのメイン モジュールを指定することです => main.js このファイルは、require.js によって最初にロードされます。
// require.js のデフォルトのファイルサフィックスは js であるため、main.js は main; と省略できます。
3 メインモジュール main.js の書き方
1. main.js が他のモジュールに依存しない場合は、JavaScript コードを直接記述できます。
// main.js
alert('読み込み成功!');
2. main.js がモジュールに依存している場合は、AMD 仕様で定義されている require() 関数を使用する必要があります
require(['moduleA','moduleB','moduleC'],function(moduleA,moduleB,moduleC){
// ...
})
// require() 関数は 2 つのパラメータを受け取ります:
// パラメータ 1: 依存するモジュール、つまりメイン モジュールが依存する 3 つのモジュールを示す配列
//パラメータ 2: コールバック関数。以前に指定したすべてのモジュールが正常にロードされた後に呼び出され、ロードされたモジュールがパラメータとして関数に渡されるため、これらのモジュールはコールバック関数内で使用できます。
// require() はモジュールを非同期的にロードします。ブラウザは応答を失いません。指定されたコールバック関数は、前のモジュールが正常にロードされた後でのみ実行され、依存関係の問題が解決されます。
例:
require(['jquery','underscore','backbone'],function($,_,Backbone){
// ...
});
4 つのモジュールの読み込み
//require.config() メソッドを使用して、モジュールの読み込み動作をカスタマイズします。
// require.config() はメインモジュール (main.js) の先頭に記述されます
// パラメータはオブジェクトであり、このオブジェクトの paths 属性は各モジュールの読み込みパスを指定します。
// 以下の 3 つのモジュールのファイルがデフォルトで main.js と同じディレクトリを使用するように設定します。
require.config({
パス:{
"jquery":"jquery.min",
"アンダースコア":"アンダースコア.min",
"バックボーン":"バックボーン.分"
}
});
// ロードされたモジュールとメイン モジュールが同じディレクトリにない場合は、パスを 1 つずつ指定する必要があります。
require.config({
"jquery":"lib/jquery.min",
"アンダースコア":"lib/underscore.min",
"バックボーン":"lib/backbone.min"
}
});
// またはベースディレクトリ (baseUrl) を直接変更します
require.config({
baseUrl:"js/lib",
パス:{
"jquery":"jquery.min",
"アンダースコア":"アンダースコア.min",
"バックボーン":"バックボーン.分"
}
});
// モジュールが別のホスト上にある場合は、その URL を直接指定することもできます
require.config({
"jquery":"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
}
});
// require.js では、各モジュールが個別の js ファイルである必要があります。この場合、複数のモジュールが読み込まれると、複数の HTTP リクエストが発行され、Web ページの読み込み速度に影響します。
// したがって、require.js は最適化ツールを提供します。モジュールをデプロイした後、このツールを使用して複数のモジュールを 1 つのファイルにマージし、HTTP リクエストの数を減らすことができます。
5 つの AMD モジュールを作成する方法
// 具体的には、モジュールは特定の define() 関数を使用して定義する必要があります。モジュールが他のモジュールに依存しない場合は、define() 関数で直接定義できます。 // math.js で数学モジュールを定義 // math.js 定義(関数(){
var add = function(x,y){
return x y;
};
return {
add:add
};
});
//main.js に数学モジュールをロードします
require(['math'],function(math){
alert(math.add(1,1));
});
// このモジュールが他のモジュールにも依存している場合、define() 関数の最初のパラメータはモジュールの依存関係を示す配列でなければなりません。
// math.js
定義(['myLib'],function(myLib){
function foo(){
myLib.doSomething();
}
return {
ふー:ふー
};
});
// require() 関数が上記のモジュールをロードすると、myLib.js ファイルが最初にロードされます
;
6 非標準モジュールのロード
// 非標準モジュールをロードするには、require() でロードする前に、まず require.config() メソッドを使用してその特性の一部を定義する必要があります。
require.config({
シム:{
'アンダースコア':{
エクスポート:'_'
},
'バックボーン':{
deps:['アンダースコア','jquery'],
エクスポート:'バックボーン'
}
}
});
// require.config() は、前述の paths 属性に加えて、互換性のないモジュールを構成するために特別に使用される shim 属性も受け取ります。
// (1) モジュールの依存関係を示す deps 配列を定義します。
// (2). 外部から呼び出されるときのこのモジュールの名前を示すエクスポート値 (出力変数名) を定義します。
例: jQuery プラグイン
シム:{
'jquery.scroll':{
deps:['jquery'],
エクスポート:'jQuery.fn.scroll'
}
};
7 つの require.js プラグイン
1.domready: ページ DOM 構造がロードされた後にコールバック関数を実行できます。
// DOM の準備ができたら呼び出されます;
})
2.テキストと画像: require.js がテキストと画像ファイルをロードできるようにします。
Define(['text!review.txt','image!cat.jpg'],function(review,cat){
console.log(レビュー);
document.body.appendChild(cat);
});