关于模块化:爪哇学习笔记JavaScript模块化变迁史

1. 幼年期——无模块化按性能将js代码放到不同的JS文件,在模板中通过script标签按需援用 <script src="a.js"></script><script src="b.js"></script>文件拆散是模块化的第一步 存在的问题: 净化全局作用域 => 不利于大型项目的开发及多人团队的共建2. 成长期——命名空间模式繁多全局变量JavaScript中一个风行的命名空间模式是抉择一个全局变量作为次要的援用对象。比方jQuery库就是应用这种形式。var myApplication = (function () { function(){ //... }, return{ //... }})();命名空间前缀命名空间前缀模式其思路十分清晰,就是抉择一个独特的命名空间,而后在其前面申明申明变量、办法和对象。var myApplication_propertyA = {};var myApplication_propertyB = {};function myApplication_myMethod() {}对象字面量表示法对象字面量模式能够认为是蕴含一组键值对的对象,每一对键和值由冒号分隔,键也能够是代码新的命名空间。var myApplication = { // 能够很容易的为对象字面量定义性能 getInfo:function() { // *** }, // 能够进一步撑持对象命名空间 models:{}, views:{ pages:{} }, collections:{}};嵌套命名空间嵌套命名空间模式能够说是对象字面量模式的升级版,它也是一种无效的防止抵触模式,因为即便一个命名空间存在,它也不太可能领有同样的嵌套子对象。var myApplication = myApplication || {}; // 定义嵌套子对象 myApplication.routers = myApplication.routers || {}; myApplication.routers.test = myApplication.routers.test || {};IIFE(Immediately Invoked Function Expression,立刻调用函数表达式)IIFE实际上就是立刻执行匿名函数。在JavaScript中,因为变量和函数都是在这样一个只能在外部进行拜访的上下文中被显式地定义,函数调用提供了一种实现公有变量和办法的便捷形式。IIFE是用于封装利用程序逻辑的罕用办法,以爱护它免受全局名称空间的影响,其在命名空间方面也能够施展其非凡的作用。var namespace = namespace || {};(function( o ){ o.foo = "foo"; o.bar = function(){ return "bar"; };})(namespace);console.log(namespace);// 定义一个简略的模块const iifeModule = (() => { let count = 0; return { increase: () => ++count, reset: () => { count = 0; } }})();iifeModule.increase();iifeModule.reset();// 依赖其余模块的IIFEconst iifeModule = ((dependencyModule1, dependencyModule2) => { let count = 0; return { increase: () => ++count, reset: () => { count = 0; } }})(dependencyModule1, dependencyModule2);iifeModule.increase();iifeModule.reset();// Revealing Module(揭示模块)模式const iifeModule = (() => { let count = 0; function increaseCount() { ++count; } function resetCount() { count = 0; } return { increase: increaseCount, reset: resetCount }})();iifeModule.increase();iifeModule.reset();/** * 揭示模块模式定义: * 在模块模式的根底上,在返回的公有范畴内,从新定义所有的函数和变量。并返回一个匿名的对象。他领有所有指向公有函数的指针。 * Module模式最后被定义为一种在传统软件工程中为类提供公有和共有封装的办法。JS这里最后应用IIEF封装 **/命名空间注入命名空间注入是IIFE的另一个变体,从函数包装器外部为一个特定的命名空间“注入”办法和属性,应用this作为命名空间代理。这种模式的长处是能够将性能行为利用到多个对象或命名空间。var myApplication = myApplication || {};myApplication.utils = {};(function () { var value = 5; this.getValue = function () { return value; } // 定义新的子命名空间 this.tools = {};}).apply(myApplication.utils);(function () { this.diagnose = function () { return "diagnose"; }}).apply(myApplication.utils.tools);命名空间注入是用于为多个模块或命名空间指定一个相似的性能根本集,但最好是在申明公有变量或者办法时再应用它,其余时候应用嵌套命名空间曾经足以满足需要了。主动嵌套的命名空间function extend(ns, nsStr) { var parts = nsStr.split("."), parent = ns, pl; pl = parts.length; for (var i = 0; i < pl; i++) { // 属性如果不存在,则创立它 if (typeof parent[parts[i]] === "undefined") { parent[prats[i]] = {}; } parent = parent[parts[i]]; } return parent;}// 用法var myApplication = myApplication || {};var mod = extend(myApplication, "module.module2");3. 成熟期CJS——CommonJS每个文件就是一个模块,有本人的作用域。在一个文件外面定义的变量、函数、类,都是公有的,对其余文件不可见。如果想在多个文件分享变量,必须定义为global对象的属性。CommonJS标准规定,每个模块外部,module变量代表以后模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。require办法用于加载模块。为了不便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。 ...

March 17, 2022 · 3 min · jiezi

关于模块化:模块化演变ESM基础知识与NodejsCMS关系

模块化演变CommonJS标准 一个文件就是一个模块每个模块都有独自的作用域通过module.exports导出成员通过require函数载入模块同步模式加载模块因为同步模式加载模块,不实用浏览器,于是呈现了AMD(Asynchronous Module Definition异步模块定义标准)并呈现了Require.js,实现了AMD标准,用define定义。然而应用起来绝对简单,模块JS文件申请频繁 EsModule个性1,通过给 script 增加 type = module 的属性,就能够以 ES Module 的规范执行其中的 JS 代码了 <script type="module"> console.log('this is es module') </script>2,ESM 主动采纳严格模式,疏忽 'use strict' <script type="module"> console.log(this) // 会打印undefined </script>3,每个 ES Module 都是运行在独自的公有作用域中 <script type="module"> var foo = 100 console.log(foo) </script> <script type="module"> console.log(foo) // undefined </script>4,ESM 是通过 CORS 的形式申请内部 JS 模块的5,ESM 的 script 标签会提早执行脚本 导出导出的只是一个援用,导出的是寄存值得地址 export {name,age}导入导入中的from不能省略掉.js文件名,须要填写残缺文件路径名。也能够应用残缺URL来加载文件.import不能放在相似if这种嵌套语法中,须要放在文件顶层。如果须要动静加载,应用import()函数,返回一个promise。 import('./module.js').then(function(module){ console.log(module) // 返回对象在module中})如果导出内容很多,有多个对象,还有一个default。导入的时候其余对象能够失常导入,如果想导入import成员,须要重命名 export {a,b}export default "c";//---------------------import {a,b default as c} from "module.js"//或者如下,tilte能够随便命名import title,{a,b} from "module.js"导出导入成员我的项目中常常会呈现一些专用模块,比方component,business,page等相似的公众区域,应用的时候挨个导入会很麻烦,能够新建一个index.js文件,对立导出 ...

January 29, 2022 · 1 min · jiezi

关于模块化:模块化

模块化从本文你将理解到什么是模块化模块化的进化史当下罕用的模块化标准 CommonJS,ES ModuleES Module个性ES Module应用in Browsers , Node.jsES Modules in Node.js - 与 CommonJS 交互ES Modules in Node.js - 与 CommonJS 差别模块化前端开发范式 是一种思维依据性能不同将代码划分不同模块,从而进步开发效率,升高保护老本模块化的进化史stage-1文件划分形式 <body> <h1>模块化演变(第一阶段)</h1> <h2>基于文件的划分模块的形式</h2> <p> 具体做法就是将每个性能及其相干状态数据各自独自放到不同的文件中, 约定每个文件就是一个独立的模块, 应用某个模块就是将这个模块引入到页面中,而后间接调用模块中的成员(变量 / 函数) </p> <p> 毛病非常显著: 所有模块都间接在全局工作,没有公有空间,所有成员都能够在模块内部被拜访或者批改, 而且模块一段多了过后,容易产生命名抵触, 另外无奈治理模块与模块之间的依赖关系 </p> <script src="module-a.js"></script> <script src="module-b.js"></script> <script> // 命名抵触 method1() // 模块成员能够被批改 name = 'foo' </script></body>module-a.jsvar name = 'module-a'function method1 () { console.log(name + '#method1')}function method2 () { console.log(name + '#method2')}stage-2命名空间形式 <body> <h1>模块化演变(第二阶段)</h1> <h2>每个模块只裸露一个全局对象,所有模块成员都挂载到这个对象中</h2> <p> 具体做法就是在第一阶段的根底上,通过将每个模块「包裹」为一个全局对象的模式实现, 有点相似于为模块内的成员增加了「命名空间」的感觉。 </p> <p> 通过「命名空间」减小了命名抵触的可能, 然而同样没有公有空间,所有模块成员也能够在模块内部被拜访或者批改, 而且也无奈治理模块之间的依赖关系。 </p> <script src="module-a.js"></script> <script src="module-b.js"></script> <script> moduleA.method1() moduleB.method1() // 模块成员能够被批改 moduleA.name = 'foo' </script></body>****module-a.jsvar moduleA = { name: 'module-a', method1: function () { console.log(this.name + '#method1') }, method2: function () { console.log(this.name + '#method2') }}stage-3 IIFE形式 ...

June 5, 2021 · 4 min · jiezi

关于模块化:前端模块化

一、模块化的了解1.什么是模块?将一个简单的程序根据肯定的规定(标准)封装成几个块(文件), 并进行组合在一起块的外部数据与实现是公有的, 只是向内部裸露一些接口(办法)与内部其它模块通信2.模块化的进化过程全局function模式 : 将不同的性能封装成不同的全局函数 编码: 将不同的性能封装成不同的全局函数问题: 净化全局命名空间, 容易引起命名抵触或数据不平安,而且模块成员之间看不出间接关系function m1(){ //...}function m2(){ //...}namespace模式 : 简略对象封装 作用: 缩小了全局变量,解决命名抵触问题: 数据不平安(内部能够间接批改模块外部的数据)let myModule = { data: 'www.baidu.com', foo() { console.log(`foo() ${this.data}`) }, bar() { console.log(`bar() ${this.data}`) }}myModule.data = 'other data' //能间接批改模块外部的数据myModule.foo() // foo() other data这样的写法会裸露所有模块成员,外部状态能够被内部改写。 IIFE模式:匿名函数自调用(闭包) 作用: 数据是公有的, 内部只能通过裸露的办法操作编码: 将数据和行为封装到一个函数外部, 通过给window增加属性来向外裸露接口问题: 如果以后这个模块依赖另一个模块怎么办?// index.html文件<script type="text/javascript" src="module.js"></script><script type="text/javascript"> myModule.foo() myModule.bar() console.log(myModule.data) //undefined 不能拜访模块外部数据 myModule.data = 'xxxx' //不是批改的模块外部的data myModule.foo() //没有扭转 </script>// module.js文件(function(window) { let data = 'www.baidu.com' //操作数据的函数 function foo() { //用于裸露有函数 console.log(`foo() ${data}`) } function bar() { //用于裸露有函数 console.log(`bar() ${data}`) otherFun() //外部调用 } function otherFun() { //外部公有的函数 console.log('otherFun()') } //裸露行为 window.myModule = { foo, bar } //ES6写法})(window)最初失去的后果: ...

February 14, 2021 · 5 min · jiezi

关于模块化:Webpack模块化原理图解

Webpack模块化原理图解为什么须要模块化场景1A同学开发了模块a,B同学开发了模块b,在页面下通过如下形式进行援用 <script src="a.js"></script><script src="b.js"></script>这时模块a,模板b中的代码都裸露在全局环境中,如果模块a中定义了一个办法del。同学b并不知道,在模块b中也定义了一个办法del。这时便造成了命名抵触的的问题。 场景2C同学开发了一个公共的工具库utils.js,D同学开发了一个公共的组件tab.js,tab.js依赖utils.js。同学E须要应用D同学开发的tab.js,就须要通过如下形式援用 <script src="util.js"></script><script src="tab.js"></script>同学E本人也开发了一个dailog.js同时它也依赖util.js。当初页面同时援用了dialog.js和tab.js,代码如下 <script src="util.js"></script><script src="dialog.js"></script><scrpt src="tab.js"></script>同学E不仅须要同时援用这三个js文件,还必须保障文件之间的援用程序是正确的。同时,从下面的代码咱们无奈间接看出模块与模块之间的依赖关系,如果不深刻tab.js,咱们无奈晓得tab.js到底是只依赖util.js还是dialog.js或者两者都依赖。随着我的项目逐步增大,不同模块之间的依赖关系则会变的越来越难以保护也会导致许多模块中大量的变量都裸露在全局环境中。 模块化的几种实现计划模块化的标准有很多种, 如下| 标准 | 实现计划 | | --- | --- | | CommonJS | node.js || AMD | Require.js || CMD | Sea.js| UMD | || ES6 Module | | webpack反对CommonJS,AMD,ESModule等多种模块化形式的语法 webpack的模块化原理图解在webpack中,所有皆模块。上面咱们通过webpack来打包以下代码 目录构造如下: 代码如下: // webpack.config.jsconst path = require('path');module.exports = { entry: 'a.js', output: { path: path.resolve(__dirname, "dist"), filename: "[name].js" }, resolve: { modules: [path.resolve(__dirname)] }, optimization: { minimize: false }}// a.jsvar b = require('b');module.exports = b.text + ' world';// b.jsexports.text = 'hello';在simple目录下执行webpack命令,会在simple目录下生成dist/output.js文件。 ...

February 1, 2021 · 1 min · jiezi