为什么要使用模块模式?
因为在全局作用域中声明的变量和函数都自动成为全局对象Window的属性,这经常会导致命名冲突,还会导致一些非常重要的可维护性难题,全局变量越多,引入错误BUG的概率就越大!所以我们应当尽可能少地使用全局变量,模块化的目的之一就是为了解决该问题的!
零全局变量模式
该模式应用场景较少,通过一个IIFE(立即执行的匿名函数),将所有代码包装起来,这样一来所有的变量、函数都被隐藏在该函数内部,不会污染全局。
使用情景:
当该代码不会被其它代码所依赖时;
当不需要在运行时不断的扩展或修改该代码时;
当代码较短,且无需和其它代码产生交互时;
单全局变量模式
基本定义
单全局变量模式即只创建一个全局变量(或尽可能少地创建全局变量),且该全局变量的名称必须是独一无二的,不会和现在、将来的内置API产生冲突,将所有的功能代码都挂载到这个全局变量上。
它已经被广泛应用于各种流行的类库中,如:
YUI定义了唯一的YUI全局对象
JQuery定义了两个全局对象,$和JQuery
Dojo定义了一个dojo全局对象
Closure定义了一个goog全局对象
例子:
var Mymodule= {}; Mymodule.Book = function(){...}; Mymodule.Book.prototype.getName = function(){....}; Mymodule.Car = function(){...}; Mymodule.Car.prototype.getWheels = function(){....};
一个模块的定义
模块是一种通用的功能片段,它并没有创建新的全局变量或命名空间,相反,所有的代码都存放于一个单函数中,可以用一个名称来表示这个模块,同样这个模块可以依赖其他模块。
function CoolModule(){ var something = 'cool'; var another = [1,2,3]; function doSomething(){ console.log( something); } function doAnother(){ console.log(another.join('!')); } return { doSomething: doSomething, doAnother: doAnother }; } var foo = CoolModule(); foo.doSomething(); //cool foo.doAnother(); //1!2!3
这里的CoolModule 就是一个模块,不过它只是一个函数,这里调用CoolModule函数来创建一个模块的实例foo,此时就形成了闭包(因为CoolModule返回一个对象,其中的一个属性引用了内部函数),模块CoolModule返回的对象就是该模块的公共API(也可以直接返回一个内部函数)
所以,模块模式需要具备两个必要条件:
必须有外部的封闭函数,且该函数必须至少被调用一次(每次调用都会创建一个新的模块实例),如CoolModule
封闭函数必须至少有一个内部函数被返回,这样内部函数才能在私有作用域中形成闭包,并且可以访问或修改私有的状态
单例模块模式的实现:
var foo = ( function CoolModule(){ ...//代码同上例 })(); foo.doSomething(); foo.doAnother();
还可以通过在模块内部保留对公共API对象的内部引用,这样就可以在内部对模块实例进行修改,包括添加、删除方法和属性
function CoolModule(){ var something = 'cool'; var another = [1,2,3]; function change() { pubicAPI.doSomething = doAnother; } function doSomething(){ console.log( something); } function doAnother(){ console.log(another.join('!')); } var pubicAPI = { change: change, doSomething: doSomething }; return pubicAPI; } var foo = CoolModule(); foo.doSomething(); //cool foo.change(); foo.doSomething(); //1!2!3 var foo1 = CoolModule(); foo1.doSomething(); //cool
现代的模块机制
命名空间是简单的通过在全局变量中添加属性来表示的功能性分组。
将不同功能按照命名空间进行分组,可以让你的单全局变量变得井然有序,同时可以让团队成员能够知晓新功能应该在哪个部分中定义,或者去哪个部分查找已有功能。
例如:定义一个全局变量Y,Y.DOM下的所有方法都是和操作DOM相关的,Y.Event下的所有方法都是和事件相关的。
常见的用法是为每一个单独的JS文件创建一个新的全局变量来声明自己的命名空间;
每个文件都需要给一个命名空间挂载功能;这时就需要首先保证该命名空间是已经存在的,可以在单全局变量中定义一个方法来处理该任务:该方法在创建新的命名空间时不会对已有的命名空间造成破坏,使用命名空间时也不需要再去判断它是否存在。
var MyGolbal = { namespace: function (ns) { var parts = ns.split('.'), obj = this, i, len = parts.length; for(i=0;i<len;i++){ if(!obj[parts[i]]){ obj[parts[i]] = {} } obj = obj[parts[i]]; } return obj; } }; MyGolbal.namespace('Book'); //创建Book MyGolbal.Book; //读取 MyGolbal.namespace('Car').prototype.getWheel = function(){...}
大多数模块依赖加载器或管理器,本质上都是将这种模块定义封装进一个友好的API
var MyModules = (function Manager() { var modules = {}; function define(name, deps, impl) { for(var i=0; i<deps.length; i++){ deps[i] = modules[deps[i]]; } modules[name] = impl.apply(impl,deps); } function get(name) { return modules[name]; } return { define: define, get: get }; })();
以上代码的核心是modules[name] = impl.apply(impl,deps);,为了模块的定义引入了包装函数(可以传入任何依赖),并且将模块的API存储在一个根据名字来管理的模块列表modules对象中;
使用模块管理器MyModules来管理模块:
MyModules.define('bar',[],function () { function hello(who) { return 'let me introduce: '+who; } return{ hello: hello }; }); MyModules.define('foo',['bar'],function (bar) { var hungry = 'hippo'; function awesome() { console.log(bar.hello(hungry).toUpperCase()); } return { awesome: awesome }; }); var foo = MyModules.get('foo'); foo.awesome();//LET ME INTRODUCE: HIPPO
异步模块定义(AMD):
define('my-books', ['dependency1','dependency2'], function (dependency1, dependency2) { var Books = {}; Books.author = {author: 'Mr.zakas'}; return Books; //返回公共接口API } );
通过调用全局函数define(),并给它传入模块名字、依赖列表、一个工厂方法,依赖列表加载完成后执行这个工厂方法。AMD模块模式中,每一个依赖都会对应到独立的参数传入到工厂方法里,即每个被命名的依赖最后都会创建一个对象被传入到工厂方法内。模块可以是匿名的(即可以省略第一个参数),因为模块加载器可以根据JavaScript文件名来当做模块名字。要使用AMD模块,需要通过使用与AMD模块兼容的模块加载器,如RequireJS、Dojo来加载AMD模块
requre(['my-books'] , function(books){ books.author; ... } )
以上所说的模块都是是基于函数的模块,它并不是一个能被稳定识别的模式(编译器无法识别),它们的API语义只是在运行时才会被考虑进来。因此可以在运行时修改一个模块的API
未来的模块机制
ES6为模块增加了一级语法支持,每个模块都可以导入其它模块或模块的特定API成员,同样也可以导出自己的API成员;ES6的模块没有‘行内’格式,必须被定义在独立的文件中(一个文件一个模块)ES6的模块API更加稳定,由于编译器可以识别,在编译时就检查对导入的API成员的引用是否真实存在。若不存在,则编译器会在运行时就抛出‘早期’错误,而不会像往常一样在运行期采用动态的解决方案;
bar.js
function hello(who) { return 'let me introduce: '+who; } export hello; //导出API: hello
foo.js
//导入bar模块的hello() import hello from 'bar'; var hungry = 'hippo'; function awesome() { console.log(hello(hungry).toUpperCase()); } export awesome;//导出API: awesome
baz.js
//完整导入foo和bar模块 module foo from 'foo'; module bar from 'bar'; foo.awesome();
import可以将一个模块中的一个或多个API导入到当前作用域中,并分别绑定在一个变量上;
module会将整个模块的API导入并绑定到一个变量上;
export会将当前模块的一个标识符(变量、函数)导出为公共API;
模块文件中的内容会被当做好像包含在作用域闭包中一样来处理,就和函数闭包模块一样;
Atas ialah kandungan terperinci 如何实现JS代码的模块化. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Penggunaan utama JavaScript dalam pembangunan web termasuk interaksi klien, pengesahan bentuk dan komunikasi tak segerak. 1) kemas kini kandungan dinamik dan interaksi pengguna melalui operasi DOM; 2) pengesahan pelanggan dijalankan sebelum pengguna mengemukakan data untuk meningkatkan pengalaman pengguna; 3) Komunikasi yang tidak bersesuaian dengan pelayan dicapai melalui teknologi Ajax.

Memahami bagaimana enjin JavaScript berfungsi secara dalaman adalah penting kepada pemaju kerana ia membantu menulis kod yang lebih cekap dan memahami kesesakan prestasi dan strategi pengoptimuman. 1) aliran kerja enjin termasuk tiga peringkat: parsing, penyusun dan pelaksanaan; 2) Semasa proses pelaksanaan, enjin akan melakukan pengoptimuman dinamik, seperti cache dalam talian dan kelas tersembunyi; 3) Amalan terbaik termasuk mengelakkan pembolehubah global, mengoptimumkan gelung, menggunakan const dan membiarkan, dan mengelakkan penggunaan penutupan yang berlebihan.

Python lebih sesuai untuk pemula, dengan lengkung pembelajaran yang lancar dan sintaks ringkas; JavaScript sesuai untuk pembangunan front-end, dengan lengkung pembelajaran yang curam dan sintaks yang fleksibel. 1. Sintaks Python adalah intuitif dan sesuai untuk sains data dan pembangunan back-end. 2. JavaScript adalah fleksibel dan digunakan secara meluas dalam pengaturcaraan depan dan pelayan.

Python dan JavaScript mempunyai kelebihan dan kekurangan mereka sendiri dari segi komuniti, perpustakaan dan sumber. 1) Komuniti Python mesra dan sesuai untuk pemula, tetapi sumber pembangunan depan tidak kaya dengan JavaScript. 2) Python berkuasa dalam bidang sains data dan perpustakaan pembelajaran mesin, sementara JavaScript lebih baik dalam perpustakaan pembangunan dan kerangka pembangunan depan. 3) Kedua -duanya mempunyai sumber pembelajaran yang kaya, tetapi Python sesuai untuk memulakan dengan dokumen rasmi, sementara JavaScript lebih baik dengan MDNWebDocs. Pilihan harus berdasarkan keperluan projek dan kepentingan peribadi.

Peralihan dari C/C ke JavaScript memerlukan menyesuaikan diri dengan menaip dinamik, pengumpulan sampah dan pengaturcaraan asynchronous. 1) C/C adalah bahasa yang ditaip secara statik yang memerlukan pengurusan memori manual, manakala JavaScript ditaip secara dinamik dan pengumpulan sampah diproses secara automatik. 2) C/C perlu dikumpulkan ke dalam kod mesin, manakala JavaScript adalah bahasa yang ditafsirkan. 3) JavaScript memperkenalkan konsep seperti penutupan, rantaian prototaip dan janji, yang meningkatkan keupayaan pengaturcaraan fleksibiliti dan asynchronous.

Enjin JavaScript yang berbeza mempunyai kesan yang berbeza apabila menguraikan dan melaksanakan kod JavaScript, kerana prinsip pelaksanaan dan strategi pengoptimuman setiap enjin berbeza. 1. Analisis leksikal: Menukar kod sumber ke dalam unit leksikal. 2. Analisis Tatabahasa: Menjana pokok sintaks abstrak. 3. Pengoptimuman dan Penyusunan: Menjana kod mesin melalui pengkompil JIT. 4. Jalankan: Jalankan kod mesin. Enjin V8 mengoptimumkan melalui kompilasi segera dan kelas tersembunyi, Spidermonkey menggunakan sistem kesimpulan jenis, menghasilkan prestasi prestasi yang berbeza pada kod yang sama.

Aplikasi JavaScript di dunia nyata termasuk pengaturcaraan sisi pelayan, pembangunan aplikasi mudah alih dan Internet of Things Control: 1. Pengaturcaraan sisi pelayan direalisasikan melalui node.js, sesuai untuk pemprosesan permintaan serentak yang tinggi. 2. Pembangunan aplikasi mudah alih dijalankan melalui reaktnatif dan menyokong penggunaan silang platform. 3. Digunakan untuk kawalan peranti IoT melalui Perpustakaan Johnny-Five, sesuai untuk interaksi perkakasan.

Saya membina aplikasi SaaS multi-penyewa berfungsi (aplikasi edTech) dengan alat teknologi harian anda dan anda boleh melakukan perkara yang sama. Pertama, apakah aplikasi SaaS multi-penyewa? Aplikasi SaaS Multi-penyewa membolehkan anda melayani beberapa pelanggan dari Sing


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Dreamweaver CS6
Alat pembangunan web visual

Muat turun versi mac editor Atom
Editor sumber terbuka yang paling popular

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini