19

require js のドキュメントや多くのチュートリアルで説明されているものよりも、require js で別の定義「構文」を使用している人を見てきました。

通常のdefine "syntax" :

define(['module/first'], function (firstModule) {
   //Module code with a dependency on module/first goes here.
});

別の定義 "構文" :

<script data-main="app/config" src="assets/js/libs/require.js"></script>

ファイル: config.js:

require.config({
   paths: {
      jquery:      '../assets/js/libs/jquery'
   }
});
require(['app']);

ファイル: app.js:

define(function(require) {
     var FirstModule = require('modules/first');
     //Module code with a dependency on module/first goes here.

この代替「構文」を使用する利点と欠点は何ですか?

4

1 に答える 1

41

あなたの説明は少し誤解を招くと思います。どちらの場合も、ファイルを指定する属性を使用してトップレベルのrequire呼び出しを行い、data-mainさまざまなモジュールを要求するプロセスを開始します。

したがって、通常、HTML に次のように記述します。

<script data-main="app/config" src="assets/js/libs/require.js"></script>

次に、どちらの場合もapp/config、構成を設定するファイルがあり (ただし、これは HTML で直接行うこともできます)、さらに重要なことrequireにモジュールを呼び出します。

require.config({
  paths: {
    jquery:      '../assets/js/libs/jquery'
  }
});
require(['app']);

さて、これらのスタイルが異なるのは、依存関係を持つモジュールを定義するときです。amd スタイルでは、モジュール名 (パス) を配列として渡し、同じ数の引数を取る関数を渡します。

app.js

define(['module/first', 'module/second', 'module/third'], function (firstModule, secondModule, thirdModule) {
  // use firstModule, secondModule, thirdModule here
});

単純化された CommonJS 構文では、インラインで必要なモジュールを渡しrequireてから、require するだけです。define

app.js

define(function(require) {
  var firstModule = require('modules/first');
  var secondModule = require('modules/second');
  var thirdModule = require('modules/third');
  // use firstModule, secondModule, thirdModule here

}

元の質問に戻ると、amd スタイルに対する CommonJS スタイルの利点は明らかです。

1 つには、従来の構文では、必要なモジュールが多数ある場合、モジュールを間違った変数名に誤って割り当てることが非常に簡単です。この一般的なケースを考えてみましょう:

define(['jquery', 'underscore', 'backbone', 'modules/first', 'modules/second', 'modules/third', 'i18n', 'someOtherModule'], function ($, _, Backbone, first, second, third, I18n, someOtherModule) {
  // ...
});

このリストに新しいモジュールを追加するときは、対応する新しい関数の引数が適切な場所に表示されるように非常に注意する必要があることがすぐにわかります。そうしないと、jQuery をBackboneなどに割り当てることができます。追跡が困難な非常に微妙なバグを作成する可能性があります。

次に、CommonJS 構文を考えてみましょう。

define(function(require) {
  var $ = require('jquery');
  var _ = require('underscore');
  var Backbone = require('backbone');
  var firstModule = require('modules/first');
  var secondModule = require('modules/second');
  var thirdModule = require('modules/third');
  var I18n = require('i18n');
  var someOtherModule = require('someOtherModule');
  // ...
}

ご了承ください:

  1. モジュールと変数名のペアリングは非常に明確です。
  2. 配列と関数の間のマッピングとしてではなく、変数名が個別にペアになっているため、require ステートメントの順序は重要ではありません。
  3. モジュールを最初に割り当てる必要はありません。モジュールが実際に使用される前であれば、どこにでも割り当てることができます。

これらは思いつく理由のほんの一部で、他にもあると思います。基本的に、依存関係が 1 つまたは 2 つしかない場合は、どちらの構文でも問題ありません。ただし、モジュールの依存関係の複雑なネットワークがある場合は、おそらく CommonJS 構文が適しています。

RequireJS ドキュメントでは、この小さな注意事項について言及されていることに注意してください。

すべてのブラウザーで使用可能な Function.prototype.toString() の結果が得られるわけではありません。2011 年 10 月の時点では、PS 3 およびそれ以前の Opera Mobile ブラウザにはありません。これらのブラウザーは、ネットワーク/デバイスの制限のためにモジュールの最適化されたビルドを必要とする可能性が高いため、RequireJS オプティマイザーなど、これらのファイルを正規化された依存配列形式に変換する方法を知っているオプティマイザーを使用してビルドを行ってください。

しかし、これは大きな問題ではありません:

この toString() スキャンをサポートできないブラウザーの数は非常に少ないため、すべてのモジュールにこのシュガー形式を使用しても安全です。特に、モジュールの値を保持する変数と依存関係の名前を並べたい場合はそうです。

于 2012-12-14T03:54:47.827 に答える