谈一谈匿名函数立即执行(IIFE)的写法

谈一谈匿名函数立即执行(IIFE)的写法

今天在写setTimeout时,遇到了匿名函数执行的问题,记录研究一下。

写法

匿名函数立即执行,IIFE (Immediateoly-Invoked Function Expressions),基本上差不多,都这样:

(function(){
  console.log('a IIFE ?')
})();

写法,还有很多种:

!function(){
  console.log('a IIFE ?')
}();

new function(){
  console.log('a IIFE ?')
}();

+function(){
  console.log('a IIFE ?')
}();

void function(){
  console.log('a IIFE ?')
}();

(function(){
  console.log('a IIFE ?')
}());

分号

对于末尾的;分号,最好还是顺手加上,因为如果不加,遇到两个都是用括号()包裹执行的IIFE时,就会遇到问题,比如:

(function(){
  console.log('a')
})()

(function(){
  console.log('b')
})()

只有a可以显示,b会报错(intermediate value)(...) is not a function

这里有个灵活的地方,如果上面的b函数括号位置修改一下,改为放在内容:

(function(){
  console.log('a')
})()

(function(){
  console.log('b')
}())

那么a,b都可以显示,但也会报同样的错误,稍后再做分析。

不加分号,上面的内容会被JS理解为:

(function(){
  console.log('a')
})()(function(){
  console.log('b')
})()

也就是说,a匿名函数执行后,没有;的隔断,后面的b立即执行函数与a合成了一个函数。执行到输出完a时,没有reutrn,后面的()相当于对undefined进行了执行,所以报错。

依然不加;,我把上面的内容修改一下就看明白了:

(function(){
  return function(){
    console.log('a')
  }
})()

(function(){
  console.log('b')
}())

这个执行结果是:

b
a

为什么是这样呢,而不是顺序输出?

首先来看看哪里做了修改:把a函数增加了一个return,也就是说,在执行完a函数部分时,得到的并不是输出内容,而是返回了一个新的匿名函数:

function(){
    console.log('a')
  }

在此基础上,执行完b函数,先得到输出b

好了,到了关键的地方,为什么接着输出了a

先说结果:

(function(){
  console.log('b')
}())

这部分执行完,对前面新返回的匿名函数进行了执行,于是得到a

来举个例子,为什么能执行:

+function(){
 console.log('i can be executed');
}('nothing here')

不仅是()本身可以执行函数,在其中增加内容也是没有任何影响,依然发挥执行函数的作用。

回到前面的例子,b函数部分

(function(){
  console.log('b')
}())

相当于在括号内部进行了匿名函数执行,输出b之后,又发挥了()执行函数的功能,使得前半部return得到的匿名函数得以执行,最终输出了a

说了这么多,还是要记得写;才是最重要的,就可以避免出现这种错误。

something cool?

为了试验分析,我尝试了好多种写法,发现几种有趣的:

!function(){
  return function(){
    return function(){
      return function(){
        return function(){
          return function(){
            return function(){
              return function(){
                console.log('so cool')
              }
            }
          }
        }
      }
    }
  }
}()()()()()()()();
(()=>()=>()=>()=>()=>()=>console.log('super cool'))()()()()()();

小细节

1.使用ES6箭头函数执行IIFE时,需要使用()包裹才可以,! + - void new等方法不可以。

比如:

()=> console.log(666)()
//这样没反应

!()=> console.log(666)()
//直接报错 Unexpected token )

(()=> console.log(666))();
//带()才行

2.前面那个分号的例子中,如果观察仔细,你会发现:

(function(){
  return function(){
    console.log('a')
  }
})()

(function(){
  console.log('b')
}())
//这里值得注意

如果换成:

(function(){
  return function(){
    console.log('a')
  }
})()

('cool')

没问题,都不会报错。

但是不换成cool的话,()内部的匿名函数:

function(){
  console.log('b')
}()

是正常执行了,可要是把这个写法原封不动,执行一下可是要报错的,因为没有这样的IIFE的写法。至于为什么,我也不太清楚,未来深入学习的时候会留心观察的。

END

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值