ホームページ > 記事 > ウェブフロントエンド > JavaScript のモジュラー思考
JS を深く研究して使用するうちに、次の 2 つの問題が徐々に見つかりました:
(1) 以前に書いた JS コードの再利用性が非常に低い
(2) 機能が分散している たとえば、次の 2 つの問題が見つかりました。現在の日付を取得する関数と、現在の日付に明日の日付である 1 を加えた関数を取得する関数を前に 2 つの独立した関連性のない関数として書きましたが、よく考えてみると、これらは実際には日付の 2 つのメソッドとして分類できます。オブジェクトを作成し、それらをバインドします。 1 つのオブジェクトをその 2 つのメソッドとして使用した方がよいのではないでしょうか?
1. まず、なぜモジュール性を使用する必要があるのかを理解する必要があります。
機能はすべてニーズを解決するために設計されています。モジュール化によってもたらされる利点は次のとおりです:
(1) 保守性。たとえば、モジュール化を使用していないコードを油と水が混在していることにたとえると、モジュール化後のコードは、油は油、水は水の階層構造を持っています。明確な機能。 JS のモジュール化の全体的な傾向を指すには、必然的に層化する水と油の現象を使用するのが適切であると思われます。
(2) 名前空間。ここで、JS のスコープについて説明する必要があります。再びスコープチェーンが関係します。スコープ チェーンに詳しくない場合は、私の他の記事「JavaScript のスコープ チェーンについて」を参照してください。 JS では、スコープを区別するために関数が使用されます。すべての関数にはスコープ チェーンがあります。すべてのコードをまとめる場合、コード行数が少ない場合は問題ありませんが、コード行数が多すぎると、必然的に「名前空間汚染」が発生します。
(3) 再利用可能。ネームスペースを理解すると、ネームスペースを利用してモジュール コードをカプセル化できるため、この関数が必要なときにいつでもこの汎用モジュールを直接参照できます。
次に、私の JS コード パスを使用して、コードをモジュール化する方法を示します。
(1) 元の時代: ページ上の <script> タグのペアで使用されるすべての JS コードを積み上げます。 </script>
function f1(){ //函数体 } function f2(){ //函数体 }
この方法で書くことの欠点: 基本的にコードの再利用性がなく、ページと密接に統合されすぎるという問題が発生する可能性があります。スコープに関するさまざまな問題も考慮する必要があります。
(2) 古代: モジュールをオブジェクトとして記述するという考えです。たとえば、ページの音楽の再生、停止、次の曲、前の曲を制御できる関数を作成したいとします。 musicPlayer オブジェクトをカプセル化できます
// 将基本的方法封装起来 var musicPlayer = { var musicDom = null, //播放器对象 var musicList = [], //存放歌曲列表 // 初始化音乐播放器 var init = function(){ }, // 添加一首歌曲 var add = function(src){ }, // 根据数组下标决定播放哪一首,索引index从0开始 var play = function(index){ }, // 暂停播放 var stop = function(){ }, // 下一首 var next = function(){ }, // 上一首 var prev = function(){ } };
この時点では、グローバル スコープでは、musicPlayer オブジェクトを window オブジェクトにバインドするだけで、musicPlayer を使用して ' フォームを追加できます。内部のメソッド。 "musicPlayer.init();" など
このメソッドには欠点もあります。つまり、公開したいコンテンツを制御できず、musicPlayer オブジェクトの内部メソッドと変数が外部で書き換えられる可能性があります。
(3) モダン。 IIFE(即時実行機能)、増幅モード、ワイド増幅モード、入力グローバル変数を含む
IIFEを除いて、他の3つはこれまでに触れたことはありません。ここで私の理解について簡単に話します。
- IIFE (即時呼び出し関数式)
// 创建一个立即执行的匿名函数 // 该函数返回一个对象,包含你要暴露的属性 // 如下代码如果不使用立即执行函数,就会多一个属性i // 如果有了属性i,我们就能调用counter.i改变i的值 // 对我们来说这种不确定的因素越少越好 var counter = (function(){ var i = 0; return { get: function(){ return i; }, set: function( val ){ i = val; }, increment: function() { return ++i; } }; }()); // counter其实是一个对象 counter.get(); // 0 counter.set( 3 ); counter.increment(); // 4 counter.increment(); // 5 counter.i; // undefined i并不是counter的属性 i; // ReferenceError: i is not defined (函数内部的是局部变量)
上記のコードからわかるように、counter には i 属性はなく、返される内容が公開されるだけです。このようにして、i を非公開にしました。
- 増幅モード
増幅モードについての私の理解は、元の関数をパラメータとして IIFE に渡し、元の関数に新しい拡張メソッドを追加して、拡張された関数を返すことです。これにより本来の機能の「増幅」を実現します。
var module1 = (function (mod){ mod.m3 = function () { //... }; return mod; })(module1);
この例では、新しいメソッド m3 が module1 に追加されて返されます。
- ワイド倍率モード
ワイド倍率モードでは、倍率モードに基づいた新しい機能が追加されます。IIFE のパラメーターは空のオブジェクトにすることができます。渡される
var module1 = ( function (mod){ //... return mod; })(window.module1 || {});
IIFEパラメータ: window.module1が定義されている場合はパラメータを渡し、未定義の場合は空のオブジェクトを渡します。
- グローバル変数を入力します
IIFE 内でグローバル変数を使用したい場合は、パラメータを通じてグローバル変数を渡すのが最善です。
var module1 = (function ($, YAHOO) { //... })(jQuery, YAHOO);
上記のコードは、jQuery ライブラリと YUI ライブラリのグローバル変数をパラメータとして module1 に渡します。