ホームページ >ウェブフロントエンド >フロントエンドQ&A >フロントエンドモジュラーAMDとCMDの違いは何ですか?

フロントエンドモジュラーAMDとCMDの違いは何ですか?

青灯夜游
青灯夜游オリジナル
2020-11-18 09:41:252314ブラウズ

違い: AMD と CMD は、依存モジュールの実行タイミングの処理が異なります。AMD は事前依存関係を推奨し、モジュールを定義するときに依存するモジュールを宣言します。CMD は、特定の場合にのみ近くの依存関係を推奨します。モジュールをインストールするときに必要になります。

フロントエンドモジュラーAMDとCMDの違いは何ですか?

JavaScript 開発の初期には、シンプルなページ操作ロジックをほんの数語で実装することが目的でしたが、現在では CPU とブラウザのパフォーマンスが大幅に向上しています。多くのページ ロジックがクライアントに移行されました (フォーム検証など)。Web2.0 時代の到来により、Ajax テクノロジが広く使用され、jQuery やその他のフロントエンド ライブラリが際限なく登場し、フロントエンドコードはますます拡張されています 現時点では、JavaScript は組み込みとして使用されています スクリプト言語の位置付けは揺らいでいますが、JavaScript はコードを整理するための明白な助けを提供しません クラスの概念さえありませんモジュールどころか、JavaScript の非常に単純なコード構成仕様では、このような大規模なコードを管理するには十分ではありません。 「このような大規模なコードは処理できません。他の言語が大規模なプログラミングを処理する方法から学ぶことができます。Java には、

パッケージ

という重要な概念があります。論理的に関連するコードは同じパッケージに編成されます。」パッケージは比較的独立した王国ですので、名前の衝突を心配する必要はありません。

import

対応するパッケージ

import java.util.ArrayList;
残念ながら、JavaScript は設計時の配置の関係で同様の機能を提供していません。開発者は、複雑な JavaScript コードを分離して整理するために、同様の機能をシミュレートする必要があります。これをモジュール性と呼びます。 モジュールは特定の機能を実装したファイルです。モジュールを使用すると、他の人のコードをより便利に使用したり、必要な機能に必要なモジュールをロードしたりできます。モジュール開発は一定の規範に従う必要があり、勝手なことをするとみんながめちゃくちゃになってしまいます

仕様策定のプロセスは苦痛ですフロントエンドの先駆者はスラッシュアンドの段階からスタートしましたこの段落を簡単に理解しましょう 特別な旅関数のカプセル化

関数について話したとき、私たちは関数の 1 つの機能は、特定のロジックを実装するためのステートメントのセットをパッケージ化することであると述べましたが、JavaScript のスコープは関数に基づいているため、モジュール化の最初のステップとして関数を使用するのは自然です。ファイルは最初のモジュールです。

function fn1(){
    statement
}

function fn2(){
    statement
}

この方法では、必要に応じて、関数が配置されているファイル内の関数を呼び出すだけで済みます。

このアプローチの欠点は明らかです。グローバル変数を汚染し、変数名が他のモジュールと競合しないという保証はなく、モジュールのメンバー間に関係はありません。

Object

上記の問題を解決するために、すべてのモジュール メンバーを 1 つのオブジェクトにカプセル化できるオブジェクト記述方法が登場しました。

var myModule = {
    var1: 1,

    var2: 2,

    fn1: function(){

    },

    fn2: function(){

    }
}

この方法では、モジュールを呼び出したいときに対応するファイルを参照し、

myModule.fn2();

これにより、モジュール名が一意であり、同じモジュール内のメンバーも関連している限り、変数の汚染を回避できます

これは良い解決策のように見えますが、欠点もあります。外部メンバーは内部メンバーを自由に変更できます

myModel.var1 = 100;
これにより、予期しないセキュリティ上の問題が発生します

関数をすぐに実行してください

関数をすぐに実行することで、詳細を非表示にするという目的を達成できます

var myModule = (function(){
    var var1 = 1;
    var var2 = 2;

    function fn1(){

    }

    function fn2(){

    }

    return {
        fn1: fn1,
        fn2: fn2
    };
})();

このようにして、公開していない変数や関数をモジュールの外部で変更することはできません

上記のアプローチはモジュール化の基礎です。現在、一般的な JavaScript モジュール仕様には主に 2 つのタイプがあります:

CommonJS

AMD

CommonJS

まず CommonJS について話しましょう Web ページにはモジュール式プログラミングがないため、ページの JavaScript ロジックだけが複雑ですが、それでも動作しますが、サーバー側にモジュールが必要です。したがって、JavaScript は長年にわたって Web 側で開発されてきましたが、最初に普及したモジュラー仕様はサーバーサイド JavaScript アプリケーションによってもたらされ、CommonJS 仕様は NodeJS に引き継がれ、これが JavaScript モジュラー プログラミングの正式な段階となります。 モジュールの定義

CommonJS 仕様によれば、単一のファイルがモジュールです。各モジュールは個別のスコープです。つまり、モジュール内で定義された変数は、グローバル オブジェクトの属性として定義されていない限り、他のモジュールから読み取ることはできません。

モジュール出力:

モジュールにはエクスポート

module.exports
    オブジェクトが 1 つだけあり、モジュールが出力したいコンテンツをこのオブジェクトに入れる必要があります

  1. モジュールをロードします:
  2. require

    メソッドを使用してモジュールをロードします。このメソッドはファイルを読み取って実行し、ファイル内の
    module.exports オブジェクトを返します

  3. 例を見てみましょう
  4. //模块定义 myModel.js
    
    var name = 'Byron';
    
    function printName(){
        console.log(name);
    }
    
    function printFullName(firstName){
        console.log(firstName + name);
    }
    
    module.exports = {
        printName: printName,
        printFullName: printFullName
    }
    
    //加载模块
    
    var nameModule = require('./myModel.js');
    
    nameModule.printName();

    実装が異なると、パスを要求する場合の要件が異なります。通常、
    js 拡張子を省略したり、相対パスや絶対パスを使用したり、さらにはパスを使用したりすることもできます。パスを直接省略し、モジュール名を使用します (モジュールが組み込みシステム モジュールである場合)

    ぎこちないブラウザ

仔细看上面的代码,会发现require是同步的。模块系统需要同步读取模块文件内容,并编译执行以得到模块接口。

这在服务器端实现很简单,也很自然,然而, 想在浏览器端实现问题却很多。

浏览器端,加载JavaScript最佳、最容易的方式是在document中插入script 标签。但脚本标签天生异步,传统CommonJS模块在浏览器环境中无法正常加载。

解决思路之一是,开发一个服务器端组件,对模块代码作静态分析,将模块与它的依赖列表一起返回给浏览器端。 这很好使,但需要服务器安装额外的组件,并因此要调整一系列底层架构。

另一种解决思路是,用一套标准模板来封装模块定义,但是对于模块应该怎么定义和怎么加载,又产生的分歧:

AMD

AMD 即Asynchronous Module Definition,中文名是异步模块定义的意思。它是一个在浏览器端模块化开发的规范

由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是大名鼎鼎RequireJS,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出

requireJS主要解决两个问题

  1. 多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器
  2. js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长

看一个使用requireJS的例子

// 定义模块 myModule.js
define(['dependency'], function(){
    var name = 'Byron';
    function printName(){
        console.log(name);
    }

    return {
        printName: printName
    };
});

// 加载模块
require(['myModule'], function (my){
  my.printName();
});

语法

requireJS定义了一个函数 define,它是全局变量,用来定义模块

define(id?, dependencies?, factory);
  1. id:可选参数,用来定义模块的标识,如果没有提供该参数,脚本文件名(去掉拓展名)
  2. dependencies:是一个当前模块依赖的模块名称数组
  3. factory:工厂方法,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值

在页面上使用require函数加载模块

require([dependencies], function(){});

require()函数接受两个参数

  1. 第一个参数是一个数组,表示所依赖的模块
  2. 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块

require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

CMD

CMD 即Common Module Definition通用模块定义,CMD规范是国内发展出来的,就像AMD有个requireJS,CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同

语法

Sea.js 推崇一个模块一个文件,遵循统一的写法

define

define(id?, deps?, factory)

因为CMD推崇

  1. 一个文件一个模块,所以经常就用文件名作为模块id
  2. CMD推崇依赖就近,所以一般不在define的参数中写依赖,在factory中写

factory有三个参数

function(require, exports, module)

require

require 是 factory 函数的第一个参数

require(id)

require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口

exports

exports 是一个对象,用来向外提供模块接口

module

module 是一个对象,上面存储了与当前模块相关联的一些属性和方法

demo

// 定义模块  myModule.js
define(function(require, exports, module) {
  var $ = require('jquery.js')
  $('p').addClass('active');
});

// 加载模块
seajs.use(['myModule.js'], function(my){

});

AMD与CMD区别

关于这两个的区别网上可以搜出一堆文章,简单总结一下

最明显的区别就是在模块定义时对依赖的处理不同

  • AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块

  • CMD推崇就近依赖,只有在用到某个模块的时候再去require

这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都支持对方的写法

AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同

requireJS は非同期読み込みモジュールであり、SeaJS は同期読み込みモジュールであると多くの人が言います。この理解は実際には不正確です。実際、読み込みモジュールはすべて非同期ですが、AMD はフロントエンドに依存しており、js は簡単にそれを知ることができます依存モジュールは誰ですか。すぐにロードされ、CMD は近くの依存関係に依存します。どのモジュールに依存しているかを知るには、モジュールを使用して文字列に変換し、再度解析する必要があります。これは多くの人が批判している点でもありますCMD. 開発の利便性をもたらすためにパフォーマンスを犠牲にしています。実際、モジュールの解析では無視できるほど時間が短いです。

なぜこの 2 つの違いは、依存するモジュールの実行タイミングの違いであると言えるのでしょうか? ADM は非同期で、CMD は同期であると多くの人が考えていますか (名前を除いて...)

モジュールも非同期でロードされます。AMD は、モジュールをロードした後に、変更されたモジュールを実行します。すべてのモジュールがロードされた後、実行されると、require コールバック関数に入り、メイン ロジックが実行されます。この効果はモジュールの実行順序に依存します。書き込み順序と一致しない場合があります。ネットワーク速度に応じて、どれが最初にダウンロードされ、どれがダウンロードされるかが決まります。 1 つが最初に実行されますが、メイン ロジックはすべての依存関係がロードされた後に実行する必要があります。

CMD は、特定の依存モジュールをロードした後は実行されません。ダウンロードされるだけです。すべての依存モジュールがロードされた後、メインロジック. 対応するモジュールは、require ステートメントが見つかった場合にのみ実行されます. このようにして、モジュールの実行順序と書き込み順序は完全に一貫しています.

これは、多くの人が AMD のユーザー エクスペリエンスであると言うことでもあります遅延がなく、依存モジュールが事前に実行されるため、優れています。ユーザーが必要な場合にのみ実行されるため、CMD のパフォーマンスが優れています。

プログラミング関連の知識の詳細については、こちらをご覧ください: プログラミング ビデオ# ##! !

以上がフロントエンドモジュラーAMDとCMDの違いは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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