JavaScript模块化开发流程分步讲解
作者:dawn 发布时间:2024-06-05 09:11:18
接触了Vue模块化开发才发现JavaScript组件化开发的演变一直在继续,以前也没有特别在意这一块内容,写着代码能调试运行不报错就可以了,主要编程语言标准就是ECMAScript5和ECMAScript6(2015年发布),使用ECMAScript6规范编写的程序需要转译器将代码编译为ECMAScript5才能为浏览器支持。作为前度开发者了解这些以及ECMAScript5和ECMAScript6的写法区别即可。
比如,ECMAScript5的写法:
var MyModuleName = {
Property1: "",
Property2: "",
Config: {
SetName1:"",
SetName2:""
},
Method1: function() {},
Method2: function() {}
};
对应的ECMAScript6的写法:
export const MyModuleName = {
Property1: "",
Property2: "",
Config: {
SetName1: "",
SetName2: ""
},
myMethod1() {},
myMethod2() {}
};
其实学习前端开发仅仅知道大概是不行的,现在把这一块的内容详细梳理一下。
1、使用传统的全局命名空间
这样情况下的缺点显而易见:
⑴全局变量无法控制是否冲突;
⑵成员函数之间看不出直接关系。
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>最原始的模式</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
contentId.innerHTML="a+b="+add(a,b);
viewId.appendChild(contentId);
function add(a,b){
return a+b;
}
function subtract(a,b){
return a-b;
}
</script>
</body>
</html>
可以出正确结果,如果进行所谓的模块化开发,就是将代码不同文件化来进行。
主文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>最原始的模式</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
</script>
<script src="module2.js"></script>
<script src="module1.js"></script>
</body>
</html>
module1.js代码:
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
contentId.innerHTML="a+b="+add(a,b);
viewId.appendChild(contentId);
module2.js代码:
var add=function(a,b){
return a+b;
}
var subtract=function(a,b){
return a-b;
}
但是这导致可能因为文件引入顺序而出现运行错误,如果文件多了,依赖不容易检查,那么纠错就是一件让人头疼的事情了。
2、使用对象的写法
缺点:
⑴暴露所有模块成员;
⑵内部状态可以被外部改写;
⑶多文件化后依赖关系不好处理。
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用对象写法</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
var MyUtils=new Object({
Property1: "as",
add:function(a,b){
return a+b;
},
subtract:function(a,b){
return a-b;
}
});
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
var result=MyUtils.add(a,b);
contentId.innerHTML="a+b="+result;
viewId.appendChild(contentId);
</script>
</body>
</html>
3、使用命名空间的写法
前端开发者基本上都使用过JQuery.js来进行前端开发,JQuery.js主要使用率命名空间模式来组织代码,定义了一个全局变量 $ 或 jQuery,该变量是一个对象,包含了所有 jQuery 提供的功能。当使用 $或者jQuery 时,实际上就是访问这个全局变量。而 jQuery 库中所有的方法和属性都是在这个全局变量上定义的。
缺点:
⑴无法解决相互依赖问题特别是多文件化后;
⑵代码组织形式逐渐复杂化;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用命名空间的写法</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
var MyApp = {
UI: {
//定义UI操作内容
},
Data: {
//定义Data内容
},
Service: {
//定义Service的内容
},
Utils: {
//定义工具类内容
add:function(a,b){
return a+b;
},
subtract:function(a,b){
return a-b;
}
}
};
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
var result=MyApp.Utils.add(a,b);
contentId.innerHTML="a+b="+result;
viewId.appendChild(contentId);
</script>
</body>
</html>
最开始常见的写法也可以是这样的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用IIFE(立即执行函数)写法</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
//定义全局变量
var MyUtils={};
//定义子命名空间
var MyUtils.UI={};
var MyUtils.Data={};
var MyUtils.Service={};
var MyUtils.Utils={};
//在子命名空间中定义内容
var MyUtils.Utils.add=function(a,b){
return a+b;
};
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
var result=MyUtils.add(a,b);
contentId.innerHTML="a+b="+result;
viewId.appendChild(contentId);
</script>
</body>
</html>
4、使用IIFE的写法
缺点:
⑴外部代码无法读取内部的变量;
⑵无法彻底解决模块间的相互依赖问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用IIFE(立即执行函数)写法</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
var MyUtils=(function(){
Property1: "as";
var add=function(a,b){
return a+b;
};
var subtract=function(a,b){
return a-b;
}
return {
add:add,
subtract:subtract
}
})();
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
var result=MyUtils.add(a,b);
contentId.innerHTML="a+b="+result;
viewId.appendChild(contentId);
//外部代码无法读取内部的变量。
</script>
</body>
</html>
要解决外部访问对象内部数据,可以对外暴露方法:
var a=1,b=2;
var MyUtils=(function(){
Property1: "as";
var add=function(a,b){
return a+b;
};
var subtract=function(a,b){
return a-b;
};
var setProperty=function(str){
this.Property1=str;
};
return {
add:add,
subtract:subtract,
setProperty
}
})();
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
var result=MyUtils.add(a,b);
contentId.innerHTML="a+b="+result;
viewId.appendChild(contentId);
MyUtils.setProperty("123");
console.log(MyUtils.Property1);
上面的代码暴露了setProperty方法,可以操作对象的内部属性值。
遵循IIFE(立即执行函数)规范很好地使用了闭包的特点,可以进行多模块的开发:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用IIFE(立即执行函数)写法</title>
</head>
<body>
<div id="view"></div>
<script>
var a=1,b=2;
var MyUtils1=(function(){
Property1: "as";
var add=function(a,b){
return a+b;
};
var setProperty=function(str){
this.Property1=str;
};
return {
add:add,
setProperty
}
})();
var MyUtils2=(function(){
Property1: "untils2";
var add=function(a,b){
return a+b;
};
var setProperty=function(str){
this.Property1=str;
};
return {
add:add,
setProperty
}
})();
//"继承"前面两个模块
var MyUtils=(function(MyUtils1,MyUtils2){
MyProperty: "MyUntils";
function add(a,b){
return MyUtils1.add(a,b);
};
function subtract(a,b){
return MyUtils1.subtract(a,b);
};
return {
add:add,
subtract:subtract
}
})(MyUtils1,MyUtils2);
const viewId=document.getElementById('view');
const contentId=document.createElement('div');
var result=MyUtils.add(a,b);
contentId.innerHTML="a+b="+result;
viewId.appendChild(contentId);
</script>
</body>
</html>
但是最终的模块严格意义上并不是真正地继承前面的两个模块,只是依赖这两个模块的注入。
本想在这一篇把所有的演变模式总结完毕,可是后续的内容太多了并且后面的内容才是重点,写到这里文字已经有点多了,还是先写到这里。
来源:https://blog.csdn.net/dawn0718/article/details/128760583


猜你喜欢
- 首先,在数据库中创建一个表,用于存放图片:CREATE TABLE Images(Id INT PRIMARY KEY AUTO_INCRE
- 不通过数据源名DSN也能访问Access数据库吗?代码如下:<% dim conn &nbs
- 一个已知管用的方法是,使用session_set_save_handler,接管所有的session管理工作,一般是把session信息存储
- 视图是一种常用的数据库对象,它将查询的结果以虚拟表的形式存储在数据中。因为视图有非常多的优点:1,可以简化操作,2,可以建立前台和后台的缓冲
- 一、文件操作1.打开r+ 打开存在文件 文件不存在 报错file = open("user.txt","r+&
- 实例如下所示:import matplotlib.pyplot as pltplt.imshow(img)#控制台打印出图像对象的信息,而图
- 需求桌面临时文件较多时,直接删了不太放心,不删又显得很杂乱,故需要写一个脚本批量清理并备份这些鸡肋的文件。所以脚本需要具有以下功能1. 可以
- Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Py
- 方法一:var tableInit = table.render({ elem:
- 本文实例讲述了Python实现合并excel表格的方法。分享给大家供大家参考,具体如下:需求将一个文件夹中的excel表格合并成我们想要的形
- django-pipeline 是一个 Django 下非常方便的静态资源管理 app,尤其是 1.2 版本之后,利用 djan
- 问题1:使用.net2005自带的SQL-Express连接不上。解决方法:1.网络防火墙阻止数据库连接;2.默认SQL-Express没有
- 在多线程程序中,它们互相独立打印的时间却是错乱的!如下图,明明t-0 > t-1 > t-2 (按照线程创建时间早晚排列)。最后
- 有以下一个表movestar(id,name,title,address),内容为:现在要查找所有具有相同的title和address的人s
- 在网上找到的随机不重复查询代码:select top 15 * from article&
- 最常用的数值类型是int,但是它未必是最佳选择。bigint,smallint,tinyint可以应用在特殊场合。他们的特性如下表所示:Da
- 每天一个JS 小demo之新建文件夹。主要知识点:DOM方法的综合运用<!DOCTYPE html><html lang=
- 本文实例总结了Python实现string字符串连接的方法。分享给大家供大家参考,具体如下:以下基于python 2.7版本,代码片段真实有
- 本文实例讲述了python使用urlparse分析网址中域名的方法。分享给大家供大家参考。具体如下:这里给定网址,通过下面这段python代
- decode()方法使用注册编码的编解码器的字符串进行解码。它默认为默认的字符串编码。语法以下是decode()方法的语法:st