IIFE 立即执行的函数表达式
介绍IIFE
- IIFE的性能
- 使用IIFE的好处
- IIFE最佳实践
- jQuery优化
在Bootstrap源码(具体请看《Bootstrap源码解析》)和其他jQuery插件经常看到如下的写法:
+function ($) {
}(window.jQuery);
这种写法称为:
IIFE (Imdiately Invoked Function Expression 立即执行的函数表达式)。
来分析这段代码
先弄清函数表达式(function expression)和 函数声明(function declaration)的区别:
函数表达式 Function Expression
var test = function() {};
函数申明 Function Declaration
function test() {}
函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量 a 来调用。
函数声明时必须有函数名。
function a(){
alert('Function declaration');
}
a();
这是一个匿名函数。
你也许注意到匿名函数在console下会报错。console的执行和报错如下:
function(){}
通过一元操作符+变成了函数表达式。也可以使用 - ~ !等其他一元运算符或者括号,目的是为了引导解析器,指明运算符附近是一个表达式。以下是三种经典方式 :
+function () {
};
(function () {
});
void function() {
};
函数表达式通过 末尾的() 来调用并运行。就是一个IIFE。
+function () {
}();
(funtion () {
})();
代码性能
运算符:+加 / -减 / ! 逻辑非 / ~位取反,返回NaN(Not A Number)。
“()”组运算符:返回表达式的执行结果undefined。
void:按运算符结合语句执行,返回 undefined。
这几种的性能对比结果:

可见+性能最差(在Firefox下差距更明显),其他几种都差不多。不过IIFE只执行一遍,对js执行效率的影响特别小,使用哪种还是看个人爱好
传参,为了避免$与其他库或者模板申明冲突,window.jQuery 作为参数传递。
+function (x) {
console.log(x);
}(3);
+function ($) {
}(window.jQuery);
使用IIFE的好处
总结有4点:提升性能、有利于压缩、避免冲突、依赖加载
1、减少作用域查找。使用IIFE的一个微小的性能优势是通过匿名函数的参数传递常用全局对象window、document、jQuery,在作用域内引用这些全局对象。
JavaScript解释器首先在作用域内查找属性,然后一直沿着链向上查找,直到全局范围。将全局对象放在IIFE作用域内提升js解释器的查找速度和性能。
传递全局对象到IIFE的一段代码示例:
// Anonymous function that has three arguments
function(window, document, $) { // You can now reference the window, document, and jQuery objects in a local scope }(window, document, window.jQuery); // The global window, document, and jQuery objects are passed into the anonymous function
2、有利于压缩。另一个微小的优势是有利于代码压缩。既然通过参数传递了这些全局对象,压缩的时候可以将这些全局对象匿名为一个字符的变量名(只要
这个字符没有被其他变量使用过)。如果上面的代码压缩后会变成这样:
3、避免全局命名冲突。当使用jQuery的时候,全局的window.jQuery对象 作为一个参数传递给$,在匿名函数内部你再也不需要担心$和其他库或者模板申明冲
突。 正如James padolsey所说:
An IIFE protects a module’s scope from the environment in which it is placed.
4、通过传参的方式,可以灵活的加载第三方插件。(当然使用模块化加载更好,这里不考虑。)举个例子,如果a页面需要使用KindEditor,a.html引入kindeditor.js
和 a.js
你可能会这么写 a.js:
$(function() {
var editor
KindEditor.ready(function(K) {
editor = K.create('textarea[data-name="kindeditor"]', {
resizeType : 1
})
})
})
b页面不需要使用Kindeditor,没有引入kindeditor.js。但是在合并JS代码后,b页面也会执行a.js中的代码,页面报错Uncaught ReferenceError: KindEditor is not defined。
也就是b页面执行了KindEditor,难道所有页面都要加载Kindeditor源文件?
可以这么修改a.js,将KindEditor变量参数化,通过给立即执行的函数表示式的参数赋值,那么其他页面都不需要加载Kindeditor源文件
+function( KindEditor){
var editor
if(KindEditor){
KindEditor.ready(function(K) {
editor = K.create('textarea[data-name="kindeditor"]', {
resizeType : 1
})
})
}
}(KindEditor || undefined)
IIFE最佳实践
反对使用IIFE的其中一个理由是可读性差,如果你有大量的JavaScript代码都在一段IIFE里,要是想查找IIFE传递的实际参数值,必须要滚动到代码最后。幸运的是,你
可以使用一个更可读的模式:
(function (library) {
// Calls the second IIFE and locally passes in the global jQuery, window, and document objects
library(window, document, window.jQuery);
}
// Locally scoped parameters
(function (window, document, $) {
// Library code goes here
}));
这种IIFE模式清晰的展示了传递了哪些全局对象到你的IIFE中,不需要滚动到长文档的最后。
jQuery优化
一段看上去写法有点像的代码。大部分项目用这段代码做作用域,这段代码会在DOM加载完成时初始化jQuery代码。
$(function(){
});
这种写法等同于
$(document).ready(function(){
// 在DOM加载完成时初始化jQuery代码。
});
$(window).load(function(){
// 在图片等媒体文件加载完成时,初始化jQuery代码。
});
结合IIFE的最佳实践,更好的写法是,立即执行document ready
+function ($) {
$(function(){
})
}(window.jQuery)
+function(yourcode) {
// The global jQuery object is passed as a parameter
yourcode(window.jQuery, window, document);
}(function($, window, document) {
// The $ is now locally scoped
// Listen for the jQuery ready event on the document
$(function() {
// The DOM is ready!
})
});
具体请看工程师,请优化你的代码
其他
在Bootstrap和其他插件中经常看到如下写法:
+function ($) { "use strict";
}(window.jQuery);
关于字符串"use strict";请看严格模式
延伸阅读:Bootstrap源码解析
参考资料:
《Javascript高级程序设计(第3版)》 7.3 模仿块级作用域
Immediately-Invoked Function Expression (IIFE) - Ben Alman
ECMA-262-3 in detail. Chapter 5. Functions. - Dmitry A. Soshnikov
Functions and function scope - Mozilla Developer Network
Named function expressions - Juriy “kangax” Zaytsev
JavaScript Module Pattern: In-Depth - Ben Cherry
Closures explained with JavaScript - Nick Morga
what does function function window jquery do - Stackoverflow
http://gregfranko.com/blog/i-love-my-iife/
【注:】转载http://suqing.iteye.com/blog/1981591
IIFE 立即执行的函数表达式的更多相关文章
- 笔记:IIFE 立即执行的函数表达式 +function ($) { }(window.jQuery);
在Bootstrap源码(具体请看<Bootstrap源码解析1>)和其他jQuery插件经常看到如下的写法: +function ($) { }(window.jQuery); 这种写法 ...
- [javascript]IIFE立即执行的函数表达式
近况:最近一直忙着找实习没有更新,不过学习还是在继续的.最近在写Node.js又稍带把javascript的角落知识捡了一遍,过半个月打算去看看python和一些CSS深层的书和博客.工作找的还好,拿 ...
- JavaScript:立即执行的函数表达式
先要理解清楚几个概念: 以下转自:http://www.cnblogs.com/TomXu/archive/2011/12/31/2289423.html 问题的核心 当你声明类似functio ...
- JS---------IIFE(Imdiately Invoked Function Expression 立即执行的函数表达式)
+function($){}(jQuery); 今天看到js代码里面有这个格式的代码,不知道啥意思,就去查了一下,我也是js小白.首先前面的+号,这个不是固定非要写+号,只要写一级运算符都可以.目的是 ...
- JS 立即执行的函数表达式(function)写法
1. 正确的写法 对于JavaScript 来说,括弧()里面不能包含语句,所以在这一点上,解析器在解析function关键字的时候,会将相应的代码解析成function表达式,而不是function ...
- JS学习笔记3_函数表达式
1.函数表达式与函数声明的区别 函数声明有“提升”(hoisting)的特性,而函数表达式没有.也就是说,函数声明会在加载代码时被预先加载到context中,而函数表达式只有在执行表达式语句时才会被加 ...
- 立即执行函数表达式(IIFE)
原文地址:benalman.com/news/2010/11/immediately-invoked-function-expression/ 译者:nzbin 也许你还没有注意到,我是一个对术语比较 ...
- javascript模块化编程-详解立即执行函数表达式IIFE
一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式. 像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...
- [转]Javascript中的自执行函数表达式
[转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...
随机推荐
- 简述Python的深浅拷贝以及应用场景
深浅拷贝的原理 深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:copy.deepcopy 字面理解:浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝 ...
- activiti 发布异常 org.activiti.engine.ActivitiException: Error parsing XML
三月 23, 2015 1:58:31 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() fo ...
- 构建Ruby开发环境(Windows+Eclipse+Aptana Plugin)
1.安装Ruby ①.从http://rubyinstaller.org/downloads/下载安装包:rubyinstaller-2.2.5-x64.exe,直接安装.(so easy) 2.安装 ...
- admin 模块功能
class CustomModelAdmin(admin.ModelAdmin): def has_module_permission(self, request): 是否会显示model def h ...
- (from) Javascript 生成指定范围数值随机数
from:http://blog.csdn.net/ilibaba/article/details/3741786 查手册后才知道, 介绍的信息少得可怜呐, 没有介绍生成 m-n 范围的随机数..., ...
- python的PIL模块安装
一.Centos安装PIL #尤其重要,否则会报错 yum install python-devel yum install libjpeg libjpeg-devel zlib zlib-devel ...
- 对象数组空指针异常说明——C#中使用对象数组必须分别为其开辟空间
l 场景 定义一个学生类,包含字段(学号,姓名,语文成绩,数学成绩,英语成绩).属性(总成绩).三个方法分别为(求平均分.数学平均分.语文平均分). 要求:在main()方法中,定义一个学生类型的数 ...
- GP DBA基本操作
1.查看队列情况 SELECT * FROM gp_toolkit.gp_resqueue_status; 如果出现了资源占用大于1.1 e+11SQL,则可能存在不合理执行计划的SQL, 基本跑不出 ...
- Linux串口编程(中断方式和select方式)
Linux下的串口编程,在嵌入式开发中占据着重要的地位,因为很多的嵌入式设备都是通过串口交换数据的.在没有操作系统的我们可以使用UART的中断来出来数据的接受和发送,而在Linux操作系统下,我们也可 ...
- Docker容器技术-命令进阶
一.基本命令 1.Docker布尔型选项 使用某选项但没有提供参数,等同于把选项设置为true,要改变它的值,唯一的方法是将其设置成false. 找出一个选项的默认值是true还是false: [ro ...