js-深入理解立即执行函数
你越是认真生活,你的生活就会越美好
——弗兰克·劳埃德·莱特
《人生果实》经典语录
什么是立即执行函数(IIFE)
看过jQuery源码
的人应该知道,jQuery开篇用的就是立即执行函数
。
立即执行函数常用于第三方库
,好处在于隔离作用域
,任何一个第三方库都会存在大量的变量和函数,为了避免变量污染
(命名冲突),开发者们想到的解决办法就是使用立即执行函数。
在了解立即执行函数之前先明确一下函数声明
、函数表达式
及匿名函数
的形式
- 函数声明
function test() {
console.log('hello world!')
}
- 函数表达式
var test = function() {
console.log('hello world!')
}
- 匿名函数
function() {
console.log('hello world!')
}
立即执行函数的两种常见形式:
- ( function(){…} )()
一个是一个匿名函数包裹在一个括号运算符中,后面再跟一个小括号 - ( function (){…} () )
一个匿名函数后面跟一个小括号,然后整个包裹在一个括号运算符中
上面两种写法等价,要想立即执行函数能做到立即执行,要注意两点
- 一是函数体后面要有小括号()
- 二是函数体必须是函数表达式而不能是函数声明。
看下面代码
除了使用()运算符
之外,!,+,-,=等运算符
都能起到立即执行的作用
。这些运算符的作用
就是将匿名函数
或函数声明
转换为函数表达式
,如下所示,函数体
是匿名函数
或者函数声明
的形式,使用运算符
将其转换为函数表达式
之后就可达到立即执行
效果:
// 输出'hello world!' 还有undefined,使用()运算符
(function(test) {
console.log(test)
})('hello world!')
(function fn(test) {
console.log(test)
})('helle world!')
// 输出'hello world!' 还有undefined,使用()运算符
(function(test) {
console.log(test)
}('hello world!'))
(function fn(test) {
console.log(test)
}('helllo world'))
// 输出'hello world!' 还有 true,使用!运算符
!function(test) {
console.log(test)
}('hello world!')
!function fn(test) {
console.log(test)
}('hello world!')
// 输出'hello world!' 还有 NaN,使用+运算符
+function(test) {
console.log(test)
}('hello world!')
+function fn(test) {
console.log(test)
}('hello world!')
// 输出'hello world!' 还有 NaN,使用-运算符
-function(test) {
console.log(test)
}('hello world!')
-function fn(test) {
console.log(test)
}('hello world!')
// 输出'hello world!' 还有 undefined,使用-运算符
var fn = function(test) {
console.log(test)
}('hello world!')
使用立即执行函数的好处
通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个“私有”的命名空间
,该命名空间的变量和方法,不会破坏污染全局的命名空间
。
此时若是想访问全局对象,将全局对象以参数形式传进去即可,如jQuery代码结构:
(function(window, undefined) {
// jQuery code
})(window)
其中window即是全局对象。
作用域隔离非常重要
,是一个JS框架必须支持的功能,jQuery被应用在成千上万的JavaScript程序中
,必须确保jQuery创建的变量
不能和导入他的程序所使用的变量
发生冲突
。
最后看一段代码
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function(val){
i = val;
},
increment: function(){
return ++i;
}
}
}());
counter.get();//0
counter.set(3);
counter.increment();//4
counter.increment();//5
conuter.i;//undefined (`i` is not a property of the returned object)
i;//ReferenceError: i is not defined (it only exists inside the closure)
推荐阅读
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强