JavaScript---js的模块化
js的模块模式被定义为给类提供私有和公共封装的一种方法,也就是我们常说的“模块化”。
怎么实现“模块化”?
通过闭包的原理来实现“模块化” ,具体实现:1.必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例);2.封闭函数必须返回至少一个内部函数(返回多个函数时,以对象字面量的形式返回)
先看一个实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function Module (){
//内部变量
var something = 'cool';
var another = [1,2,3];
//内部函数
function doSomething(){
console.log(something);
} function doAnother(){
console.log(another);
}
//返回对象字面量形式,里面包含内部函数的引用, 这样就保持了内部变量是隐藏且私有的状态。
return {
doSomething: doSomething,
doAnother: doAnother
};
}
//调用外部函数Module创建一个模块实例foo
var foo = Module();
foo.doSomething();//cool
foo.doAnother();//[1,2,3]
</script>
</body>
</html>
简单分析一下代码:
首先,Module只是一个函数,必须通过他才能创建一个模块实例,如果不执行他,内部作用域和闭包都无法被创建。 其次,Module函数返回一个字面量对象,这个返回的对象含有对内部函数而不是内部变量的引用。这样就保持了内部变量是隐藏且私有的状态。可以将这个对象类型的返回值看作模块的公共API 这个API最终会被赋值给外部的变量foo,通过他就可以访问API中的属性方法,比如:foo.doSomething()。
上面的实例中,Module函数可以调用任意多次,每次调用都会创建一个新的模块实例。当只需要一个实例时,可以对这个模块进行简单的改进来实现单例模式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
var foo = (function Module (){
var something = 'cool';
var another = [1,2,3]; function doSomething(){
console.log(something);
} function doAnother(){
console.log(another);
} return {
doSomething: doSomething,
doAnother: doAnother
};
})(); foo.doSomething();//cool
foo.doAnother();//[1,2,3]
</script>
</body>
</html>
通过将模块函数转换为IIFE(立即执行函数),立即调用这个函数并将返回值直接赋值给电力的模块实例foo
模块也是普通的函数,因此可以接收参数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
// var foo = (function Module (){
// var something = 'cool';
// var another = [1,2,3]; // function doSomething(){
// console.log(something);
// } // function doAnother(){
// console.log(another);
// } // return {
// doSomething: doSomething,
// doAnother: doAnother
// };
// })(); // foo.doSomething();//cool
// foo.doAnother();//[1,2,3] var foo = (function Module(id){
function change(){
publicAPI.id = id2;
} function id1(){
console.log(id);
} function id2(){
console.log(id.toUpperCase());
} var publicAPI = {
change: change,
id: id1
}; return publicAPI;
})('hello'); foo.id();//hello
foo.change();
foo.id();//HELLO
</script>
</body>
</html>
可以看出:通过在模块实例的内部保留公共API对象的内部引用(API指的是引用return回来的字面量对象 {...}),可以从内部模块实例进行修改,包括添加、删除方法和属性,以及修改它们的值。
现代的模块机制
大多数模块依赖加载器/管理器,本质上都是将模块定义为封装进一个API。 现在,宏观了解一下模块机制:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
var myModule = (function Module(){
var modules = [];
//定义一个define函数用于定义一个模块
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
};
})();
</script>
</body>
</html>
这段代码的核心就是:modules[name] = impl.apply(impl, deps)。 为了模块的定义(define函数)引入包装函数(可以传入任何依赖),并且将返回值,也就是模块的API,存储在一个根据名字来管理的模块列表中。(不是很理解啊??)
下面展示了如何使用它来定义模块:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
var myModule = (function Module(){
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
};
})(); myModule.define('bar', [], function(){
function hello(who){
return "Hello," + who;
}; return{
hello:hello
};
}); myModule.define('foo', ['bar'], function(bar){
var hungry = 'hippo'; function awesome(){
console.log(bar.hello(hungry).toUpperCase());
}; return {
awesome: awesome
};
}); var bar = myModule.get('bar');
var foo = myModule.get('foo'); console.log(bar.hello('hippo'));//hello, hippo
foo.awesome();//HELLO, HIPPO
</script>
</body>
</html>
‘foo’和‘bar’模块都是通过一个返回公共API的函数来定义的。‘foo’甚至接受‘bar’的实例作为依赖参数,并使用它。
这就是模块的威力!!
总结一下:模块并不是什么神秘的东西,他只是一个外部函数返回内部函数的引用(字面量对象的形式返回),从而可以访问内部函数和变量的一种方式。
---摘自《你不知道的JavaScript》(上) 2017-3-22 23:24
JavaScript---js的模块化的更多相关文章
- JAVAScript:前端模块化开发
目录 一:前端模块化概要 1.1.模块化概要 1.2.函数封装 1.3.对象封装 1.4.立即执行函数表达式(IIFE) 1.5.模块化规范 1.5.1.CommonJS 1.5.2.AMD((Asy ...
- JavaScript 中的模块化
JavaScript 中的模块化 最早的基于立即执行函数,闭包的模块化 const MountClickModule = function(){ let num = 0; const handle ...
- 简单聊一聊Javascript中的模块化
在面试中只要说到模块化的问题,多多少少总会问到这些,umd.amd.cjs.esm,可能听过其中一个两个,或者都听说过.接下来我们先简单了解一下他们到底是什么,又有什么样的区别呢. 最开始的时候,Ja ...
- javascript(js)小数精度丢失的解决方案
原因:js按照2进制来处理小数的加减乘除,在arg1的基础上 将arg2的精度进行扩展或逆扩展匹配,所以会出现如下情况. javascript(js)的小数点加减乘除问题,是一个js的bug如0.3* ...
- 【转】关于URL编码/javascript/js url 编码/url的三个js编码函数
来源:http://www.cnblogs.com/huzi007/p/4174519.html 关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),e ...
- paip.java 以及JavaScript (js) 的关系以及区别
paip.java 以及JavaScript (js) 的关系以及区别 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:// ...
- 关于URL编码/javascript/js url 编码/url的三个js编码函数
关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),encodeURI(),encodeURIComponent() 本文为您讲述关于js(javasc ...
- JavaScript js无间断滚动效果 scrollLeft方法 使用模板
JavaScript js无间断滚动效果 scrollLeft方法 使用模板 <!DOCTYPE HTML><html><head><meta charset ...
- JavaScript(js)/上
JavaScript(js) ECMA-----定义的基础语法 DOM------document object model BOM------Browser object model Jav ...
- 【HANA系列】SAP HANA XS使用JavaScript(JS)调用存储过程(Procedures)
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Jav ...
随机推荐
- vim初级命令
命令 说明 光标移动 h 左 l(小写L) 右 j 下 k 上 w 移动到下一个单词 b 移动到上一个单词 插入 i 在当前光标处进行编辑 I(大写i) 在行首插入 A 在行末插入 a ...
- spring boot 引导
链接:https://www.zhihu.com/question/39483566/answer/243413600 Spring Boot 的优点快速开发,特别适合构建微服务系统,另外给我们封装了 ...
- Jackson /常用注解/ annotation(转)
1.@JsonAutoDetect 自动检测,(作用在类上)来开启/禁止自动检测. fieldVisibility:字段的可见级别 ANY:任何级别的字段都可以自动识别 NONE:所有字段都不可以自动 ...
- java模拟http/https post请求
1.Post请求失败的代码 try { HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = respon ...
- 机器学习实战python3 决策树ID3
代码及数据:https://github.com/zle1992/MachineLearningInAction 决策树 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特 ...
- googleMapReduce
摘要 MapReduce是一个编程模型,也是一个处理和生成超大数据集的算法模型的相关实现.用户首先创建一个Map函数处理一个基于key/value pair的数据集合,输出中间的基于key/value ...
- iconnect
https://iconnect.infosysapps.com/vpn/index.html
- Java TreeMap详细介绍和使用示例
①对TreeMap有个整体认识 TreeMap是一个有序的key-value集合,它是通过红黑树实现的. TreeMap继承于AbstractMap,所以它是一个Map,即key-value集合. T ...
- 2 安装企业wiki:confluence
jira sudo /etc/init.d/jira start 启动 jiarsudo /etc/init.d/jira stop 停止 jiar 方法一:$ sudo /etc/init.d/co ...
- Axure的总结
1.Axure的用途 Axure RP 能帮助网站需求设计者,快捷而简便的创建基于网站构架图的带注释页面示意图.操作流程图.以及交互设计,并可自动生成用于演示的网页文件和规格文件,以提供演示 ...