Immediately-Invoked Function Expression(IIFE):立即调用函数表达式
使用全局变量可能会造成一些不必要的麻烦
因此我们要使用局部变量
在 java 语言中我们可以用 { } 将代码包裹起来,使它们成为局部变量
但是这在 ES5 中不行,因为 var 有变量提升
1 | { |
ES6 里面引入了 let 的概念,于是有了块级作用域
解决了这个问题,IIFE 似乎就变得不那么必要了
1 | { |
但是了解 IIFE 可以让我们初学者更好得理解函数表达式、变量提升等的概念,以及了解前端语言的发展进程,知道前人一步步将原本不那么美好的 js 变得规范化的过程,学习他们的智慧。
ES5 里面,没有块级作用域,只有函数(函数作用域)可提供局部变量环境
于是我们声明一个 function xxx,然后 xxx.call()
1 | function xxx(){ |
但是这个时候 xxx 也是全局变量(全局函数)
所以我们不能给这个函数名字,即需要使用匿名函数
1 | function(){ |
但是这在 Chrome 里会报错,js 语法错误
这是由于浏览器认为这是一个函数声明
解决办法:让浏览器去解析这个函数表达式
如给函数取反
1 | ! function(){ |
类似的还有
1 | +function(){}() |
如果实在不想改变函数返回值,也可以用圆括号
1 | (function(){}).call() |
但是方法会有不好的情况:如果括号前面有东西
1 | a |
所以不推荐
你也可以用一个随机变量名函数而不用匿名函数,永远都不会变量污染的那种变量(这种方法好吗?)
1 | function ada231231284u3lkda(){ |
当然最推荐的还是用取反 !,这就好像是个警示:我要开始用 IIFE 了
IIFE 达到了局部变量的效果,外面访问不到立即执行函数里面的变量(避免变量污染)
但有时候我们需要访问 IIFE 里面的内容,怎么办?
最简单的方法是直接用全局变量 window
1 | ! function(){ |
我们还可以在 IIFE 里面使用闭包来隐藏 a
1 | ! function(){ |
IIFE 使得 a 成为局部变量而无法被外部访问
闭包使得匿名函数可以操作 a
window.nAdd1 保存了匿名函数的地址
任何地方都可以使用 window.nAdd1
=> 任何地方都可以使用 window.nAdd1 操作 a,但是不能直接访问 a
这就是 window 和闭包联合作用的效果
闭包
将上面代码整合在一起,就是闭包的常见形式
1 | function fn(){ |
现在我们明白了为什么闭包一般在 IIFE 里出现
IIFE 提供局部变量的环境,才有闭包的用武之地
return 的作用
上面代码中的 return 和 window 的作用一样,是为了让外部能够访问函数作用域内部的函数,当然 return a.n 的作用也是如此
而闭包的作用,至此应该理解了
本文仅作为个人学习使用
相关参考:
Immediately-Invoked Function Expression (IIFE)
「每日一题」什么是立即执行函数?有什么作用?
「每日一题」JS 中的闭包是什么?
JS 标准参考教程——IIFE
ES6 入门——let#块级作用域