javascript模块化编程-详解立即执行函数表达式IIFE
一、IIFE解释
全拼Imdiately Invoked Function Expression,立即执行的函数表达式。
像如下的代码所示,就是一个匿名立即执行函数:
(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()(...)’是需要这么执行的,结果代码就报错了。
觉得不错的,可以关注模块化这个系列的文章,容我后续码字,敬请期待!
阅读原文:http://www.jianshu.com/p/4dbf4a4c8ebb
javascript模块化编程-详解立即执行函数表达式IIFE的更多相关文章
- Javascript模块化编程详解
		在这篇文章中,我将会回顾一下js模块化编程的基础,并且将会讲到一些真的非常值得一提的进阶话题,包括一个我认为是我自创的模式. 模块化编程是一种非常常见Javascript编程模式.它一般来说可以使得代 ... 
- RequireJS模块化编程详解
		1.模块的写法 模块化编程一般都有这么几个过渡过程,如下描述. 原始方法 function m1(){ //... } function m2(){ //... } 上面的函数m1()和m2(),组成 ... 
- JS006. 详解自执行函数原理与数据类型的快速转换 (声明语句、表达式、运算符剖析)
		今天的主角: Operator Description 一元正值符 " + "(MDN) 一元运算符, 如果操作数在之前不是number,试图将其转换为number. 圆括号运算符 ... 
- 详解立即执行函数(function(){}()),(function(){})()
		要知道这几种写法之间的区别,我们要先聊些题外话——js中函数的两种命名方式,即表达式和声明式. 函数的声明式写法为:function foo(){/*...*/},这种写法会导致函数提升,所有func ... 
- 理解JavaScript的立即调用函数表达式(IIFE)
		首先这是js的一种函数调用写法,叫立即执行函数表达式(IIFE,即immediately-invoked function expression).顾名思义IIFE可以让你的函数立即得到执行(废话). ... 
- (译)详解javascript立即执行函数表达式(IIFE)
		写在前面 这是一篇译文,原文:Immediately-Invoked Function Expression (IIFE) 原文是一篇很经典的讲解IIFE的文章,很适合收藏.本文虽然是译文,但是直译的 ... 
- 详解javascript立即执行函数表达式(IIFE)
		立即执行函数,就是在定义函数的时候直接执行,这里不是申明函数而是一个函数表达式 1.问题 在javascript中,每一个函数在被调用的时候都会创建一个执行上下文,在函数内部定义的变量和函数只能在该函 ... 
- 【HANA系列】SAP HANA XS使用JavaScript编程详解
		公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Jav ... 
- 【HANA系列】【第二篇】SAP HANA XS使用JavaScript编程详解
		公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第二篇]SAP HANA XS ... 
随机推荐
- Linux - 创建定时任务
			crontab命令 用来创建周期性定时任务 crontab {-l|-r|-e} -l 显示当前的 crontab -r 删除当前的 crontab -e 使用编辑器编辑当前 crontab 文件 输 ... 
- 【不遮遮掩掩】Github上传本地代码以及常见问题解决方案
			2019.20.18更新: 把完整命令打一遍吧,不然看完太累了不是 //初始化文件夹 git init //初始化目录,把基本文件下载下来,如ignore文件 git pull --rebase or ... 
- LeetCode--No.005  Longest Palindromic Substring
			5. Longest Palindromic Substring Total Accepted: 120226 Total Submissions: 509522 Difficulty: Medium ... 
- Python 离线工作环境搭建
			准备 在断网的和联网的机器安装pip,下载地址https://pypi.python.org/pypi/pip 在联网的开发机器上安装好需要的包 例如: pip3 install paramiko p ... 
- appium安装完成后运行和执行python脚本的错误合集
			1.第一个错误如下: main.js: error: argument "--app": Expected one argument. null 这个一般是appium服务端安装的 ... 
- Ubuntu下安装程序的三种方法(转)
			引言 在Ubuntu当中,安装应用程序我所知道的有三种方法,分别是apt-get,dpkg安装deb和make install安装源码包三种.下面针对每一种方法各举例来说明. 一.apt-get方法 ... 
- 《Kubernetes权威指南》——组件原理
			1 API Server 1.1 提供集群管理的API接口 API Server在kubernetes中的进程名为apiserver,运行在Master节点上 apiserver开放两个端口 本地端口 ... 
- python数据类型之内置方法
			python有六大数据类型,分别为整型.字符串.列表.字典.元祖和集合,这些基本数据类型都内置了很多方法,接下来一一探寻. python中整型有两种:int和float 1 int 使用dir函数查看 ... 
- WPF 使用 Direct2D1 画图入门
			本文来告诉大家如何在 WPF 使用 D2D 画图. 本文是一个系列 WPF 使用 Direct2D1 画图入门 WPF 使用 Direct2D1 画图 绘制基本图形 WPF 使用 SharpDX WP ... 
- 【Java】用注解实现分发器
			在C/S中,客户端会向服务器发出各种请求,而服务器就要根据请求做出对应的响应.实际上就是客户机上执行某一个方法,将方法返回值,通过字节流的方式传输给服务器,服务器找到该请求对应的响应方法,并执行,将结 ... 
