let可否彻底替代IIFE

let是什么 http://es6.ruanyifeng.com/#docs/letes6

最近,我写了一篇关于syntax of Java’s IIFE pattern的文章,来解释为何咱们用如今的方式来写当即执行函数表达式。少数的读者批评文章过期了,都在争论在ECMA 2015中介绍的块级做用域变量使IIFE变得过期了。算法

偏偏相反,当即执行函数表达式一点也没有过期!由于这个理由,我决定写这篇后续文章来介绍一些当即执行函数表达式的常见用法。注意如下的列表是不完整的,因此若是你喜欢的用法没有在文章出现,但愿你不要有什么很差的感受。windows

函数做用域 VS 块级做用域浏览器

经过var关键字声明的本地变量仅做用于当前闭包域,若是不存在这样的一个闭包函数,那么将会建立一个污染全局做用域的全局变量。为了防止这种状况出现,咱们可使用IIFE来建立一个包含有这个本地变量的函数。闭包

(function(){函数

varfoo= "bar";工具

console.log(foo);post

})();优化

foo;// ReferenceError: foo is not definedthis

目前的争论是,咱们可使用在ECMA 2015介绍的块级做用域变量来代替IIFE,以达到相同的效果。相比于函数级做用域,let和const关键字声明的本地变量仅做用于当前所处的”块”级域。

{

let foo= "bar";

console.log(foo);

}

foo;// ReferenceError: foo is not defined

然而,块级做用域变量不是当即函数执行表达式的替代品。确实,若是支持ECMA 2015,let和const可以用来限制本地变量只在包含它的块级做用域内使用。

若是,你在不支持ECMA 2015的环境(例如一些旧的浏览器)中执行你的Java代码。你就不能使用let和const关键字来建立块级做用域变量。你将不得不求助于之前经典的函数级做用域方法。

闭包和私有数据

IIFE的另外一个用法是为局部变量提供一个封装的做用域,在IIFE返回的函数中可以访问该变量。这种方式即_a closure is created_容许函数访问这个本地变量,即便这个函数在IIFE的词法范围以外执行时。

假设咱们要建立一个uniqueId函数,每次调用该函数时就会返回一个惟一的id(好比 “id_1”,“id_2”等)。在下面的IIFE中,记录了一个私有的计数变量(count),每次调用计数函数uniqueId的时候,就会将count加一。咱们在IIFE中返回的另外一个函数,这个函数在调用时会返回一个新的标识符字符串。

constuniqueId= (function(){

let count= 0;

returnfunction(){

++count;

returnid_${count};

};

})();

console.log(uniqueId());// "id_1"

console.log(uniqueId());// "id_2"

console.log(uniqueId());// "id_3"

注意,在IIEF以外没法访问这个计数变量count。除了从IIEF中返回的函数,别人没法读写该变量。这样就能建立真正的私有状态,它只能以受控的方式进行修改。revealing module pattern很是依赖于这种机制。

constcounter= (function(){

let counterValue= 0;

return{

increment(){

++counterValue;

},

get value(){

returncounterValue;

}

};

})();

counter.increment();

console.log(counter.value);// 1

counter.increment();

counter.increment();

console.log(counter.value);// 3

当使用IIFE来返回一个”封闭”一些本地变量来管理私有数据的函数时,let和const都不能替代它。

变量重命名

有时,你可能碰到一种状况,你正在使用的两个不一样的库暴露的全局变量名是相同的。例如,考虑一下你正在使用jQuery同时另外一个库也指定了一个为$的全局变量。

为了解决命名冲突问题,能够将一段代码封装在一个IIEF中,将一个全局变量(好比,jQuery)做为参数传入IIFE。在函数内部,就能够以一个任意的参数名(好比,$)来访问该参数值:

window.$= functionsomethingElse(){

// ...

};

(function($){

// ...

})(jQuery);

无论在外部做用域有什么值指定给$,在IIFE中,这些值都会被”屏蔽”,$参数一直指向jQuery方法。

捕获全局对象

Java代码在不一样环境执行时,你所使用的全局对象是不一样的。当代码在浏览器运行时,全局对象是windows。可是在Node.js中,全局对象是global。因为在写通用的Java代码时,你确定不想硬编码这两个名字其中的任何一个,这时你就可使用一种”包装”的方式就像下面这样:

(function(global){

// ...

})(this);

不论是浏览器仍是Node.js的环境,global参数将会指定到对的全局对象上。若是想了解更多关于使用这种技巧来捕获全局对象的细节内容,请移步this post by Todd Motto。

压缩方面的优化

混叠变量名的方法也能够用来优化代码,这种方式使代码可以被更有效的压缩。举例以下:

(function(window,document,undefined){

// ...

})(window,document);

一个Java压缩工具例如UglifyJS能够缩短函数的参数名为单个字母的标识符

(function(w,d,u){

// ...

})(window,document);

更短标识符名会使文件的体积变得更小。然而,若是HTTP的返回内容经过Gzip或者Deflate进行压缩,文件的大小已经被颇有效的压缩了。所以,若是结合压缩算法,压缩技术的边际收益会变得更小。因此本身权衡和比较返回内容的大小,较短的名字可能仍然是有做用的。

相关文章
相关标签/搜索