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 ...
随机推荐
- python中的基本数值计算
最近用到了python的数字信号处理,发现很多以前学的都忘掉了,这里做个笔记 # -*- coding: utf-8 -*- #计算乘方 print pow(3,4) #计算平方 import num ...
- 机器学习技法笔记:15 Matrix Factorization
Roadmap Linear Network Hypothesis Basic Matrix Factorization Stochastic Gradient Descent Summary of ...
- Servlet-转发和重定向的区别
实际发生位置不同,地址栏不同 转发是发生在服务器上的 转发是由服务器进行跳转的,细心的朋友会发现,在转发的时候,浏览器的地址栏是没有发生变化的,在我访问Servlet111的时候,即使跳转到了Serv ...
- 测试工具之Jmeter(各部件简单介绍)
jmeter可以到官网下载: http://jakarta.apache.org/ 下载后解压即可使用,双击如下文件打开Jmeter界面: $JMETER_HOME\apache-jmeter-3.1 ...
- vi/vim编辑器的使用
命令模式下操作替换字符:%s/str1/str2/g删除全部内容:%d不保存退出:q!保存退出:wq! 执行shell命令:!command 如!ls -l 在下一行插入shell命令执行 ...
- UML类图中的六种关系(物理设计阶段)
UML类图中经常会用到各种箭头和线条来表示不同类或者接口之间的关系,因此非常好的理解各个图标的含义是很有必要的. 在物理设计阶段可以通过EA工具将类图搭建好,然后直接生成物理类,这样也可以减少物理设计 ...
- jsp页面简单的验证码实现
前段时间赶着结束毕业设计任务,现在完成了.回来补一下设计毕业设计的过程中遇到的问题和解决方案. 为了使小系统更有模有样,这里尝试在登录页面实现验证码功能.现描述一下我的解决方案. 首先看一下实现后的界 ...
- [教程向]__在IDEA中使用git+github实现代码的版本控制
前言 在前面,我们对git与github有了一个简单的了解,了解到版本控制的必要性,和github远程代码仓库的一些作用.那么我们如何在IDEA重实现代码的版本控制呢. 前提 首先你要安装有git,注 ...
- 精读JavaScript模式(三),new一个构造函数居然发生了什么?
一.前言 上个月底,爸爸因为事故突然离世,说心里话,现在看到'去世','爸爸'这样的字眼,眼泪都会忍不住在眼眶打转,还是需要时间治愈.最近也只是零碎的看了下东西,始终沉不下心去读书,直到今天还是决定捡 ...
- 一张图读懂PBN飞越转弯衔接TF/CF航段计算
在PBN旁切转弯的基础上,再来看飞越转弯接TF(或CF)航段,保护区结构上有些相似,只是转弯拐角处的保护区边界有“简化”,其余部分是相近的. FlyOver接TF段的标称航迹有一个飞越之后转弯切入航迹 ...