Durch das eingehende Studium und die Verwendung von JS habe ich nach und nach zwei Probleme entdeckt:
(1) Die Wiederverwendbarkeit des JS-Codes, den ich zuvor geschrieben habe, ist sehr gering
(2) Die Funktionen sind verstreut, und zum Beispiel möchte ich das aktuelle Datum erhalten, und ich möchte auch das aktuelle Datum plus 1 erhalten, was das morgige Datum ist. Ich habe es vorher als zwei unabhängige und nicht verwandte Funktionen geschrieben, aber jetzt denke ich Darüber hinaus können sie tatsächlich als ein Datumsobjekt klassifiziert werden. Wäre es nicht besser, sie als zwei Methoden an ein Objekt zu binden?
1. Zuerst müssen wir verstehen, warum wir Modularität verwenden müssen?
Die Funktionen sind alle darauf ausgelegt, Bedürfnisse zu lösen. Zu den Vorteilen, die die Modularisierung mit sich bringen kann, gehören:
(1) Wartbarkeit. Wenn wir beispielsweise den Code, der keine Modularisierung verwendet, mit Öl und Wasser vergleichen, ist der Code nach der Modularisierung wie die Schichtung von Öl und Wasser. Ein solcher Code weist eine klare Hierarchie auf klare funktionen. Es scheint angemessen, das Phänomen der unvermeidlichen Schichtung von Öl und Wasser zu verwenden, um auf den allgemeinen Trend der JS-Modularisierung zu verweisen.
(2) Namensraum. Hier müssen wir über den Umfang von JS sprechen. Es geht wieder um die Scope-Kette. Wenn Sie mit Bereichsketten nicht vertraut sind, können Sie sich meinen anderen Artikel „Grundlegendes zu Bereichsketten in JavaScript“ ansehen. In JS werden Funktionen zur Unterscheidung von Bereichen verwendet. Jede Funktion hat eine Bereichskette. Wenn wir den gesamten Code zusammenfügen, ist eine kleine Anzahl von Codezeilen in Ordnung, aber wenn es zu viele Codezeilen gibt, führt dies unweigerlich zu einer „Namespace-Verschmutzung“.
(3) Wiederverwendbarkeit. Wenn wir den Namespace verstehen, können wir den Modulcode mithilfe des Namespace kapseln, sodass wir bei Bedarf direkt auf dieses Funktionsmodul verweisen können.
Verwenden Sie als Nächstes meinen JS-Codepfad, um zu demonstrieren, wie der Code modularisiert wird:
(1) Ursprüngliche Ära: Geben Sie alle zu verwendenden JS ein. Der Code ist gestapelt in einem Paar <script>-Tags auf der Seite. </script>
function f1(){ //函数体 } function f2(){ //函数体 }
Nachteile dieser Schreibweise: Der Code ist grundsätzlich nicht wiederverwendbar und es besteht möglicherweise das Problem, dass er zu eng in die Seite integriert ist. Sie müssen auch verschiedene Aspekte des Umfangs berücksichtigen.
(2) Antike: Die Idee ist, das Modul als Objekt zu schreiben. Beispielsweise möchten wir eine Funktion schreiben, die die Seitenmusikwiedergabe, den Stopp, das nächste Lied und das vorherige Lied steuern kann. Sie können ein MusicPlayer-Objekt kapseln
// 将基本的方法封装起来 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(){ } };
Zu diesem Zeitpunkt kann es als Modul bezeichnet werden. Im globalen Bereich binden wir nur ein MusicPlayer-Objekt an das Fensterobjekt und können dann MusicPlayer plus verwenden '.' um die darin enthaltenen Methoden aufzurufen. Zum Beispiel „musicPlayer.init();“
Diese Methode hat auch einen Nachteil: Wir können den Inhalt, den wir verfügbar machen möchten, nicht steuern und die internen Methoden und Variablen des musicPlayer-Objekts können extern neu geschrieben werden .
(3) Modern. Einschließlich IIFE (sofortige Ausführungsfunktion), Verstärkungsmodus, breiter Verstärkungsmodus, Eingabe globaler Variablen
Mit Ausnahme von IIFE bin ich noch nie mit den anderen drei Typen in Kontakt gekommen Sprechen Sie hier über mein Verständnis.
-IIFE (Immediately-Invoked Function Expression)
// 创建一个立即执行的匿名函数 // 该函数返回一个对象,包含你要暴露的属性 // 如下代码如果不使用立即执行函数,就会多一个属性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 (函数内部的是局部变量)
Wie aus dem obigen Code ersichtlich ist, gibt es im Zähler kein i-Attribut, sondern nur eines Offengelegte Inhalte zurückgeben. Auf diese Weise haben wir mich privat gemacht.
- Verstärkungsmodus
Mein Verständnis des Verstärkungsmodus besteht darin, die ursprüngliche Funktion als Parameter an IIFE zu übergeben und dann der ursprünglichen Funktion eine neue Erweiterungsmethode hinzuzufügen , Die erweiterte Funktion kehrt zurück. Dadurch wird die „Verstärkung“ der ursprünglichen Funktion erreicht.
var module1 = (function (mod){ mod.m3 = function () { //... }; return mod; })(module1);
In diesem Beispiel wird eine neue Methode m3 zu Modul1 hinzugefügt und zurückgegeben.
- Großer Vergrößerungsmodus
Der breite Vergrößerungsmodus fügt eine neue Funktion basierend auf dem Vergrößerungsmodus hinzu: Die Parameter von IIFE können leere Objekte sein.
var module1 = ( function (mod){ //... return mod; })(window.module1 || {});
IIFE-Parameter übergeben: Wenn window.module1 definiert ist, übergeben Sie den Parameter, wenn er undefiniert ist, übergeben Sie ein leeres Objekt.
- Geben Sie globale Variablen ein
Wenn wir globale Variablen innerhalb von IIFE verwenden möchten, ist es am besten, die globalen Variablen über Parameter zu übergeben.
var module1 = (function ($, YAHOO) { //... })(jQuery, YAHOO);
Der oben gezeigte Code übergibt die globalen Variablen der jQuery- und YUI-Bibliotheken als Parameter an module1.