ホームページ  >  記事  >  ウェブフロントエンド  >  なぜモジュール化が必要なのでしょうか? js での一般的なモジュラー ソリューションの紹介

なぜモジュール化が必要なのでしょうか? js での一般的なモジュラー ソリューションの紹介

不言
不言転載
2018-10-26 15:20:292598ブラウズ

この記事では、なぜモジュール化が必要なのかについての内容をお届けします。 js で一般的に使用されるモジュラー ソリューションの紹介は、参考になると思います。

モジュール化が必要な理由

ES6 が登場する前は、JS 言語自体がモジュール化機能を提供していなかったため、開発にいくつかの問題が生じましたが、その中で最も重要なのは2 つの問題は、地球規模の汚染と依存関係管理の混乱であるはずです。

// file a.js
var name = 'aaa';
var sayName = function() {
    console.log(name);
};
<!-- file index.html -->
<script src=&#39;xxx/xxx/a.js&#39;></script>

<script>
    sayName(); // 'aaa'
    
    // code...
    
    var name = 'bbb';
    
    sayName(); // 'bbb'
</script>

上記のコードでは、a.js が提供するsayName 関数を 2 回呼び出して、異なる結果を出力しました。これは明らかに、両方のファイルが変数名に値を割り当てているため、相互に影響を及ぼします。影響がありました。もちろん、コードを記述するときに既存の変数名を定義しないように注意することはできますが、ページが数百行からなる十数個のファイルを参照する場合、定義されているすべての変数を記憶するのは明らかに現実的ではありません。

// file a.js
var name = getName();
var sayName = function() {
    console.log(name)
};
// file b.js
var getName = function() {
    return 'timo';
};
<script src=&#39;xxx/xxx/b.js&#39;></script>
<script src=&#39;xxx/xxx/a.js&#39;></script>

<script>
    sayName(); // 'timo'
</script>
<script src=&#39;xxx/xxx/a.js&#39;></script>
<script src=&#39;xxx/xxx/b.js&#39;></script>

// Uncaught ReferenceError: getName is not defined

上記のコードは、複数のファイルに依存関係がある場合、特定のファイルの実行時にその依存関係が事前に読み込まれていることを確認するために、それらのファイルが導入される順序を確認する必要があることを示しています。ファイルやプロジェクトが大きくなると、より多くの依存関係を処理する必要があり、面倒でエラーが発生しやすくなることが考えられます。

これらの問題を解決するために、JS 言語のモジュール機能を提供する多くの仕様がコミュニティで登場しました。これらの仕様の助けを借りて、開発をより便利かつ安全にすることができます。

一般的なモジュール化ソリューション

CommonJS

CommonJS はコミュニティによって提案されたモジュール化ソリューションの 1 つであり、Node.js はこの設定された計画に従います。

基本的な書き方

// file a.js
var obj = {
    sayHi: function() {
        console.log('I am timo');
    };
};

module.exports obj;
// file b.js
var Obj = require('xxx/xxx/a.js');

Obj.sayHi(); // 'I am timo'

上記のコードでは、ファイルa.jsがモジュールの提供者、ファイルb.jsがモジュールの呼び出し元です。

仕様

  1. 各ファイルはモジュールです。

  2. モジュールモジュールオブジェクト内に提供されます。現在のモジュールを表す;

  3. モジュールは exports を使用して独自の関数/オブジェクト/変数などを公開します。 ## モジュールは

    require()
  4. メソッドで他のモジュールをインポートします;
  5. CommonJS の仕様は上記の 4 つだけです。基本的な記述方法の例では、実際の実装では、Node.js は CommonJS 仕様に従っていますが、それでもいくつかの調整が加えられています。

  6. AMD

AMD はモジュール仕様の 1 つであり、RequireJS はこの一連の仕様に従います。

基本的な使用法

 // file a.js
 define('module', ['m', './xxx/n.js'], function() {
    // code...
 })

上記のコードでは、ファイル a.js がモジュールをエクスポートします。

仕様

AMD では、公開されたモジュールは、define を使用します。 Function

define(moduleName, [], callback);

上記のコードに示すように、define 関数には 3 つのパラメータがあります。

moduleName このパラメータは通常、モジュールの名前を示します。ほとんど効果はありません

  • ['name1', 'name2']、2 番目のパラメータは配列であり、現在のモジュールが依存する他のモジュールを示します。依存するモジュールがない場合は、このパラメータは省略可能です

  • #callback、3番目のパラメータは必須パラメータです。これはコールバック関数です。内部は現在のモジュールの関連コードです

  • #その他
  • ADM の特徴 ADM 仕様と次に紹介する CMD 仕様の最大の違いは、コールバックを実行する前です。現在ロードされているモジュールのすべての依存パッケージが最初にロードされます。これは、2 つのパラメータで指定された依存パッケージの定義の 3 番目のステップです。

  • CDM

基本的な書き方

 define(function(require, exports, module) {   
    var a = require('./a')  
    a.doSomething();
    // code... 
    var b = require('./b') 
    // code...
})

上記のコードはCMD仕様エクスポートモジュールの基本的な書き方です。 #書き込み方法からわかる CMDの書き込み方法はAMDと非常に似ていることがわかります。主な違いは、前述のように、AMDがフロントエンドに依存していることです。 CMD 仕様では、モジュールの実行前に依存関係はロードされず、モジュールの実行中に特定の依存関係が必要になったときに再度ロードされます。

UMD

CommonJS、AMD、CMD を並行して使用する場合、それらと互換性のあるソリューションが必要になります。これにより、開発時に、それに続く仕様を考慮する必要がなくなります。依存モジュールが存在し、この問題を解決するのが UMD の登場です。

基本的な書き方

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //Node, CommonJS之类的
        module.exports = factory(require('jquery'));
    } else {
        //浏览器全局变量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //方法
    function myFunc(){};
    //暴露公共方法
    return myFunc;
}));

上記のコードはUMDの基本的な書き方です。コードからもわかるように、CommonJS仕様とAMD仕様の両方に対応しています。

ES6 モジュール

上記では、CommonJS、AMD、CMD、UMD をそれぞれ紹介しています。これらはすべて、JS のモジュール化に対するコミュニティの貢献です。この仕様が登場した根本的な理由は次のとおりです。 JS 言語にはモジュール化機能がありません。現在、JS の最新言語仕様 ES6 は、JS 独自のモジュール化ソリューションを完全に置き換えることができ、ブラウザー側で一般的に使用できます。そしてノード側。

#ES6 のモジュール化機能は、

export

import

という 2 つのコマンドで構成されます。

export

コマンドは、

import

コマンドは、他のモジュールが提供する関数をインポートするために使用されます。

export コマンドES6 のファイルはモジュールです。モジュール内の変数/関数は外部からアクセスできません。内部関数/変数を他のモジュールに公開したい場合は、次のようにします。これを使用するには、export コマンド を使用してエクスポートする必要があります。

// file a.js
export let a = 1;
export let b = 2;
export let c = 3;
// file b.js
let a = 1;
let b = 2;
let c = 3;

export {a, b, c}
// file c.js
export let add = (a, b) => {
    return a + b;
};

上面三个文件的代码,都是通过export命令导出模块内容的示例,其中a.js文件和b.js文件都是导出模块中的变量,作用完全一致但写法不同,一般我们更推荐b.js文件中的写法,原因是这种写法能够在文件最底部清楚地知道当前模块都导出了哪些变量。

import命令

模块通过export命令导出变量/函数等,是为了让其他模块能够导入去使用,在ES6中,文件导入其他模块是通过import命令进行的

// file d.js
import {a, b, c} from './a.js';

上面的代码中,我们引入了a.js文件中的变量a、b、c,import在引入其他模块内的函数/变量时,必须与原模块所暴露出来的函数名/变量名一一对应。
同时,import命令引入的值是只读的,如果尝试对其进行修改,则会报错

import {a} d from './a.js';
a = 2; // Syntax Error : 'a' is read-only;

export default命令

从上面import的介绍可以看到,当需要引入其他模块时,需要知道此模块暴露出的变量名/函数名才可以,这显然有些麻烦,因此ES6还提供了一个import default命令

// file a.js

let add = (a, b) => {
    return a+b
};
export default add;
// file b.js
import Add from './a.js';

Add(1, 2); // 3

上面的代码中,a.js通过export default命令导出了add函数,在b.js文件中引入时,可以随意指定其名称

export default命令是默认导出的意思,既然是默认导出,显然只能有一个,因此每个模块只能执行一次export default命令,其本质是导出了一个名为default的变量或函数。

以上がなぜモジュール化が必要なのでしょうか? js での一般的なモジュラー ソリューションの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。