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 ...
随机推荐
- html5的常用函数
required 验证非空 readonly 文本只读 video 视频播放标签 Ogg 带有 Theora 视频编码和 Vorbis 音 ...
- 列表中相同key的字典相加
# 怎么把列表中相同key的字典相加,也就是id的值加id的值,doc_count的值加doc_count的值 # 目标列表 l=[{'id': 5, 'doc_count': 129}, {'id' ...
- scala和正则表达式常用基础知识示例
http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html . 匹配除换行符以外的 ...
- web前端基础——初识HTML
1 HTML概念 HTML(Hypertext Markup Language)即超文本标记语言,是网页的描述语言.它其实是一种描述网页的标准,它通过给需要描述的内容加上标签,浏览器按照HTML语言的 ...
- C++之条形码,windows下zint库的编译及应用(一)
zint库是一个开源的第三方库,提供了生成条形码.二维码等功能.本文主要介绍zint库的生成及简单应用. 工具/原料 vs2012 代码文件下载 1 下载zint包 2 zint依赖另外两个库 ...
- 【c++ primer, 5e】特殊用途语言特性
[默认实参] 1.注意点:函数的默认实参可以在函数的声明中添加,但是后续声明只能添加默认参数而不能改变先前声明的默认参数.(函数的声明通常是定义在头文件上的,多次声明同一个函数是合法的) 2.默认实参 ...
- DevOps实践之持续集成Jenkins(最新版本测试)
一.安装Jenkins (1)下载并安装配置Java Development Kit 8 [root@localhost ~]# rpm -ivh jdk-8u161-linux-x64.rpm Pr ...
- cookie注入原理
cookie注入原理-->红客联盟 http://www.2cto.com/article/201202/118837.html 前言: document.cookie:表示当前浏览器中的coo ...
- 如何退出minicom【学习笔记】
一.先按ctr+a进入设置模式 二.在按x退出
- LeetCode——Unique Paths
Question A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram be ...