闭包的由来,为什么要用闭包
由于ES5之前没有块级作用域概念导致例子中我们期望的局部变量 i 被环境污染从而产生错误结果。
解决问题要用到IIFE
为什么要用IIFE
- 传统方法定义和执行分开写
- 传统的方法直接污染全局命名空间(浏览器里的 global 对象,如 window)
于是有人就想出是否可以这样写:
function foo(…){}();
当然不能,为什么呢?
因为 function foo(…){} 这个部分只是一个声明,对于解释器来说,就好像你写了一个字符串 “function foo(…){}”,它需要使用解析函数,比如 eval() 来执行它才可以。所以把 () 直接放在声明后面是不会执行,这是错误的语法。
那如何让他可以执行呢?只要把 声明 变成 表达式(Expression) 就可以了:
(function foo() {...}) // 这里是故意换行,实际上可以和下面的括号连起来
();
//等价于
var foo = function () {...}; // 这就不是定义,而是表达式了。
foo();
但是之前我们说不行的那个写法,其实也可以直接用括号包起来,这也是一种等价的表达式:
(function foo(){…}());
所以你问有没有区别?木有~
另外,刚才说过转变表达式的方式很多比如:
!function foo() {…}();
//或者
+function foo() {…}();
所谓不去污染全局命名空间,是因为 IIFE 创建了一个新的函数作用域,你真正的业务代码被封装在其中,自然就不会触碰到全局对象了。如果你需要全局对象,那就 pass 给 IIFE:
(function (global) {
// 在这里,global 就是全局对象了
})(this) // 在浏览器里,this 就是 window 对象
(function(){})(); 是 把函数当作表达式解析,然后执行解析后的函数
相当于 var a = function(){}; a(); a得到的是函数
(function(){}()); 是把函数表达式和执行当作语句直接执行、
相当于 var a = function(){}(); a得到的是结果
最终结果是一样的()只是起了自执行的作用