javascript模块化编程详解
一、IIFE解释
像如下的代码所示,就是一个匿名立即执行函数:
(function(window, undefined){ // 代码... })(window);
二、括号的意义
2.1 包住function(){}
的括号的意义
这个括号的目的,是为了把function(){}
转化为表达式。像一些库的源码,喜欢用如下方式代替:
~function(){ // 代码... }();
或者这种方式:
+function(){ // 代码... }();
其实,作用都一样,都是把function(){}
转化成一个可执行的表达式,方便执行。
如果去掉该括号,则会报错。因为单纯的function(){}
不是可执行的表达式,会直接报错。如下图:
2.1 第二个括号的意义
理解了第一个括号的意义,第二个括号就很简单了,就是执行表达式了。
三、参数的意义
以这段代码为例子,讲解参数
var wall = {}; (function(window, WALL, undefined){ })(window, wall);
参数分为形参和实参。
function(window, WALL, undefined)
三个参数为形参,第二个括号(window, wall)
的两个参数为实参。
也即可以理解为 window == window
,wall == WALL
。
2.1 普通形参
普通形参是指由window
和wall
这样的实际变量传入指定,可以为任何类型的变量。一个形参就对应一个实参
2.2 特殊形参undefined
为什么形参要多写一个undefined,这是一个很有趣的话题。
可以知道这个示例,实参只有两个,而形参有三个。所以在函数执行的时候,形参undefined
会默认赋值为undefined。
形参undefined
的作用如下:
2.2.1 防止特殊值undefined被恶意代码篡改。
IE6等低版本浏览器,undefined是支持被修改的。而这个特殊值被修改后,像以下这种判断就失效了。
if(wall == undefined){ // 代码... }
所以,这里多加一个形参的目的就是为了防止这种情况发生。只要在这个IIFE作用域内,undefined就能够正常获取到。
2.2.2 压缩代码可以压缩undefined
因为undefined作为形参,像YUI compressor这种类型的代码压缩工具,可以将其相关的值进行压缩,减小文件的体积。
四、写法解析
4.1 普通写法
var wall = {}; // 声明定义一个命名空间wall // 定义方法 (function(window, WALL, undefined){ // 给wall命名空间绑定方法say WALL.say = function(){ console.log('hello'); }; })(window, wall); (function(window, WALL, undefined){ // 给wall命名空间绑定方法 whoIam WALL.whoIam = function(){ console.log('wall'); }; })(window, wall); // 调用 wall.say(); wall.whoIam();
先定义一个命名空间,然后再给这个命名空间加东西。这是最普遍的写法,也是最好理解的。
不足的地方就是必须先声明一个命名空间,然后才能执行相关的绑定代码。存在顺序加载的问题。
4.2 放大模式
var wall = (function(window, WALL, undefined){ if(typeof WALL == 'undefined'){ WALL = {}; } // 给wall命名空间绑定方法say WALL.say = function(){ console.log('hello'); } return WALL; // 返回引用 })(window, wall); var wall = (function(window, WALL, undefined){ if(typeof WALL == 'undefined'){ WALL = {}; } // 给wall命名空间绑定方法 whoIam WALL.whoIam = function(){ console.log('wall'); } return WALL; // 返回引用 })(window, wall); // 调用 wall.say(); wall.whoIam();
放大模式的好处就是,可以不用考虑代码加载的先后顺序。
因为js允许wall
变量进行重复var声明,所以这段代码是可以执行的。
我可以把IIFE函数拆分成多个文件进行加载,而不会出现普通写法需要注意的问题。
需要注意的点:
1.IIFE的头部,都要先进行检查命名空间是否已经实例化,如果还没实例化,则进行实例化。
2.IIFE的尾部,都要return命名空间的引用,使后续代码能够得到最新的wall
命名空间内容。
4.3 宽放大模式
(function(window, WALL, undefined){ // 给wall命名空间绑定方法say WALL.say = function(){ console.log('hello'); } })(window, window.wall || (window.wall = {})); (function(window, WALL, undefined){ // 给wall命名空间绑定方法 whoIam WALL.whoIam = function(){ console.log('wall'); } })(window, window.wall || (window.wall = {})); // 调用 wall.say(); wall.whoIam();
宽放大模式的重点注意的地方:就是在实参部分的window.wall || (window.wall = {})
。
用||运算符进行取巧。
如果window.wall
是已经实例化的,非not defined。则直接返回window.wall
的引用,赋值给形参WALL
。不会执行||运算符后面的内容。
如果window.wall
还未实例化,则进行实例化。这里要注意的点是实例化是一个赋值操作,需要用括号包起来,变成表达式去执行,才不会报错。
表达式(window.wall = {})
执行完毕后,会返回新对象window.wall
的引用。
宽放大模式的好处:是可以切割成多个文件进行加载,而不必考虑文件加载的先后顺序,不存在强耦合关系。
当然,如果IIFE里面的方法互相引用,还是存在加载依赖的问题。这个问题可以用加载器Require.js等工具解决,这里就不讨论了。
五、分文件加载IIFE要注意的点
;(function(window, WALL, undefined){ // 给wall命名空间绑定方法say WALL.say = function(){ console.log('hello'); } })(window, window.wall || (window.wall = {}));
眼尖的已经看出区别了,就是文件开始的地方,先写上分号;
。
这样,多个文件合并的时候,才不会出现收尾相接,代码出现错乱的问题。比如下面这种情况:
// a.js 文件 wall.log() // b.js 文件 (function(window, WALL, undefined){ // 给wall命名空间绑定方法say WALL.say = function(){ console.log('hello'); } })(window, window.wall || (window.wall = {}));
由于a.js文件的wall.log()
少写了分号,跟b.js文件合并后,js就会认为‘wall.log()(...)’是需要这么执行的,结果代码就报错了。
觉得不错的,可以关注<a href="http://www.php.cn/js/js-weixinapp-module.html" target="_blank">模块化</a>
这个系列的文章,容我后续码字,敬请期待!
以上是javascript模块化编程详解的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

本文系列在2017年中期进行了最新信息和新示例。 在此JSON示例中,我们将研究如何使用JSON格式将简单值存储在文件中。 使用键值对符号,我们可以存储任何类型的

增强您的代码演示:开发人员的10个语法荧光笔 在您的网站或博客上共享代码片段是开发人员的常见实践。 选择合适的语法荧光笔可以显着提高可读性和视觉吸引力。 t

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

本文介绍了关于JavaScript和JQuery模型视图控制器(MVC)框架的10多个教程的精选选择,非常适合在新的一年中提高您的网络开发技能。 这些教程涵盖了来自Foundatio的一系列主题

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可
