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)

推荐阅读

连点成线
Vue源码学习完整目录


谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值