ホームページ  >  記事  >  ウェブフロントエンド  >  モジュール性は JS でどのように実装されますか?

モジュール性は JS でどのように実装されますか?

小云云
小云云オリジナル
2018-01-09 17:01:532229ブラウズ

Js の初期の位置付け (当初は過度に複雑なシナリオで使用されるとは想定していませんでした) により、モジュール システムは提供されません。アプリケーションがより複雑になるにつれて、モジュール化は解決しなければならない問題になります。 Feimai の徹底した原則に従って、モジュール化のベールを取り除く必要があります。この記事では、主に Js でのモジュール化がどのように詳細に実装されているかを紹介し、一定の参考値を持つモジュール化の操作を詳細に紹介します。興味のある方はさらに詳しく学んで、皆さんのお役に立てれば幸いです。

1. モジュール化によって解決すべき問題

何かを深く分析するには、目的を持って見る必要があります。モジュール化によって解決される問題は、一文に要約できます

地球規模の汚染を発生させずに、プロジェクト コードをより適切に構成できます

簡単な例を挙げると、次のコードができました:

function doSomething () {
 const a = 10;
 const b = 11;
 const add = function (a + b) {
  return a + b
 }
 add (a + b)
}

実際のアプリケーション内 シナリオ内、 doSomething は非常に多くのことを実行する必要がある可能性があり、追加関数はより複雑で再利用できる可能性があるため、追加関数を別のファイルに分離したいと考えています:

// doSomething.js 文件
const add = require('add.js');
const a = 10;
const b = 11;
add(a+ b);
// add.js 文件
function add (a, b) {
 return a + b;
}
module.exports = add;

これの目的は明らかです。プロジェクト コードをよりよく整理し、2 つのファイル内の require と module.exports に注目してください。現在の観点から見ると、これは CommonJS 仕様のキーワードから来ています (この仕様については後で説明する章があります)。これらはインポートとエクスポートを表します。仕様に関係なく、これは実際にはモジュール化に向けて解決する必要がある問題です。さらに、add モジュールは再利用する必要がありますが、add を導入するときに地球規模の汚染を引き起こすことは望ましくありません

2. インポートされたモジュールを実行する方法

上記の例では、コードを 2 つのモジュールに分割しています。ファイルを地球規模の汚染を引き起こすことなく、例のコードが正常に実行できるように require を実装するにはどうすればよいでしょうか?

モジュールファイルのコードの読み込みプロセスを無視し、requireがすでにモジュールファイルからコード文字列を読み取ることができると仮定すると、requireは次のように実装できます

function require (path) {
  // lode 方法读取 path 对应的文件模块的代码字符串
  // let code = load(path);
  // 不考虑 load 的过程,直接获得模块 add 代码字符串
  let code = 'function add(a, b) {return a+b}; module.exports = add';
  // 封装成闭包
  code = `(function(module) {$[code]})(context)`
  // 相当于 exports,用于导出对象
  let context = {};
  // 运行代码,使得结果影响到 context
  const run = new Function('context', code);
  run(context, code);
  //返回导出的结果
  return context.exports;
}

いくつかのポイントがあります:

1)原因 グローバル汚染の場合、コード文字列をクロージャの形式でカプセル化する必要があり、キーワード module.exports をエクスポートする必要があります。モジュールは、外部との接触の唯一のキャリアです。これを入力として使用する必要があります。クロージャ匿名関数のパラメータとリファラーによって渡されるコンテキストの関連付け

2) new Function を使用してコード文字列を実行する 一般的にはその必要がないため、ほとんどの学生は new Function に慣れていないものと推定されます。これは関数を定義するためのものです。次のように関数クラスを使用して関数を作成できることを知っておく必要があります。

var function_name = new function(arg1, arg2, ..., argN, function_body)

上記の形式では、各引数はパラメーターであり、最後のパラメーターは関数本体 (関数のコード) です。実行されます)。これらのパラメータは文字列である必要があります。つまり、eval と同様に文字列コードを実行するために使用でき、eval と比較して、文字列コード内の特定の変数の値をパラメーターの形式で渡すこともできます

3)標準のエクスポート キーワードはエクスポートのみであるのに、実際の使用では module.exports を使用する必要があるのはなぜだろうかという疑問を抱いたことがあるでしょう (Node コードを書いたことがある人はよく知っているはずです)。その場合は、このコードで答えを見つけることができます。 use exports コンテキストを受信すると、エクスポートの再割り当てはコンテキストに影響を与えません (パラメーターのアドレスが渡されます)。信じられない場合は、コードを次の形式に変更して再実行してください。

デモの結果

3. コードのロード方法

コードの実行の問題を解決するには、モジュール ファイルのコードのロードの問題も解決する必要があります。上記の例によれば、私たちの目標はモジュールをロードすることです。文字列形式のファイル コード

Node コンテナでは、すべてのモジュール ファイルはローカルにあります。ローカル ディスクからモジュール ファイルを読み取って文字列コードをロードし、上記のプロセスに従うだけです。事実は、Node の非組み込みモジュール、コアモジュール、および C++ モジュールのロードと実行メソッドがほぼ同じであることを証明しています (新しい関数ではありませんが、同様のメソッドです)

RN/Weex コンテナでは、リモートのbundle.jsをロードする必要がある場合、ネイティブの機能を通じてリモートjsファイルをリクエストし、それを文字列コードに読み込んでロードできます(このロジックによれば、Nodeはリモートjsモジュールを読み取ることができるように見えますが)ほとんどの場合、これを行う必要はありません)

ブラウザ環境では、すべての JS モジュールをリモートで読み取る必要がありますが、残念ながら、ブラウザが提供する機能の制限により、リモート JS ファイルを次の形式で直接読み取ることができません。 ajax を介したファイル ストリームは文字列コードです。前提条件が満たされない場合、上記の運用戦略は機能せず、別の方法を見つけるしかありません

これが CommonJs 仕様が存在する理由であり、AMD/CMD 仕様も存在する理由です


それではどうでしょうかブラウザ上で完了しますか?ブラウザの Js コントロールを通じてリモート Js モジュール ファイルを動的にロードするには、