IIFE为何不会污染全局变量

在开发过程当中见到的IIFE,函数表达式都是匿名的,若是咱们把它写成命名函数表达式,那全局做用域中岂不是多了一个变量,这样又怎么能保证不会污染全局变量呢?javascript

一般咱们在谈论IIFE时,都是在谈论它的用法,模块化,闭包等等,却少有说起它为何能够拿来作模块化,为何不会污染全局变量。前端

本文虽然是在说IIFE,可是并不会过多的介绍它的使用,或者其实践意义(毕竟在标准中已经ES6的今天讨论这个意义不是很大),更多的是讨论这种写法的自己在语法上会成立的缘由,为何能够在块级做用域出现以前替代它,及其中涉及到的点。java

阅读断定

考虑下面代码闭包

(function a(){
    console.log('run a');
})();
console.log(a);
复制代码

这段代码运行在严格模式下,这里说一下运行结果,a没法打印,运行到这里会报错。模块化

对运行结果存在疑惑?或许本文可以令你稍解疑惑。函数

IIFE的成立

IIFE能够看作是两部分构成,前半部分定义了一个函数表达式,后半部分的括号这是表示运行这个函数。拿一个具体的例子描述一下。组件化

(function a(){
    console.log('run a');
})();
复制代码

在上面的代码中前半部分的圆括号定义了一个函数表达式,函数后面加上圆括号表示的语法是运行这个函数。固然IIFE的写法不止这一种,还有其余诸如,使用一个圆括号将函数表达式和后面的圆括号一块儿括起来等各类写法。ui

因为标准中规定了function关键字开头是一个函数声明,因此要它变成函数表达式,咱们须要加点东西,好比在function 开头加个 +,void,-等各类运算符,总之咱们的目的是不让这一行以function开头,这样在语法解析式会认为function(){}()是一个表达式去运行它,而不是当作函数声明去解析它。看下面的例子:spa

console.log(+function s(){return 1}())      // 1
console.log(+function a(){})    // NaN
复制代码

从上面的运行过能够看出,IIFE执行时是将function(){}()总体做为了一个表达式在运行的最终得出一个结果,固然在使用IIFE时咱们并不关心返回结果。code

不会污染全局做用域的缘由

IIFE不会污染全局变量的缘由,是函数表达式的特性。

命名函数表达式

当咱们使用函数表达式建立函数时,想在函数体内部使用当前函数,可使用命名函数表达式。这个函数名称只会做为函数体内部变量。换言之,使用表达式建立的命名函数,并不能和声明函数同样在声明函数的做用域产生变量,而只会在这个命名函数内部产生这个变量,且该变量是只读的,不可被赋值。

var a = function c() {
    c = 'test';
    console.log(c); // ƒ c() {
                    // c = 'test';
                    // console.log(c);
                    // } 
}
a();
console.log(c); // c is not defined
复制代码

这里咱们能够理解,IIFE不会污染全局变量是利用了函数表式的特性,由此而衍生的种种写法,只是为了在语法上是的解释器执行时可以识别这个表达式,而后执行它。当看到了这个本质的时候,对于它的种种写法咱们就不须要去机械记忆了,咱们本身也能够写出不少。

结论

究其根本,IIFE是充分理解了语言特性并结合时代需求的产物。这里的特性更多的就是函数表达式的特性了,固然也有一部分语法特性的结合。需求固然就是所谓前端 “刀耕火种” 时代人们对组件化的探索。

放在篇文章下不合适,可是就是忽然想写的话: 记得有一种论调说,前端的发展不过是把其余语言多年前就已经实践过的思想搬过来而已,所以以为前端没什么技术含量,甚至产生优越感。可是我想说的是,思想并非某一语言,或者某一领域的全部物。不能由于年轻的事物,正在践行别人实践过的思想就认为它是在抄袭照搬的,毕竟同一个思想的实践在不一样的需求下产生的火花是能够彻底不一样的。也借此表达下前端仍是有不少独特而有意思的东西的,这一细分领域的出现不过是时代需求的产物,你们都是为需求服务的,因此没有必要产生所谓优越感或者自卑感,毕竟更好的实现需求才是根本。

相关文章
相关标签/搜索