let能否完全替代IIFE
let是什么 http://es6.ruanyifeng.com/#docs/let
最近,我写了一篇关于syntax of Java’s IIFE pattern的文章,来解释为什么我们用现在的方式来写立即执行函数表达式。少数的读者批评文章过时了,都在争论在ECMA 2015中介绍的块级作用域变量使IIFE变得过时了。
恰恰相反,立即执行函数表达式一点也没有过时!因为这个理由,我决定写这篇后续文章来介绍一些立即执行函数表达式的常见用法。注意以下的列表是不完整的,所以如果你喜欢的用法没有在文章出现,希望你不要有什么不好的感觉。
函数作用域 VS 块级作用域
通过var关键字声明的本地变量仅作用于当前闭包域,如果不存在这样的一个闭包函数,那么将会创建一个污染全局作用域的全局变量。为了防止这种情况出现,我们可以使用IIFE来创建一个包含有这个本地变量的函数。
(function(){
varfoo= "bar";
console.log(foo);
})();
foo;// ReferenceError: foo is not defined
目前的争论是,我们可以使用在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进行压缩,文件的大小已经被很有效的压缩了。因此,如果结合压缩算法,压缩技术的边际收益会变得更小。所以自己权衡和比较返回内容的大小,较短的名字可能仍然是有作用的。
let能否完全替代IIFE的更多相关文章
- JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- JavaScript学习总结(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- JavaScript学习总结(三)——闭包、IIFE、原型、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- 使用IIFE(立即执行函数)让变量私有化
今天去看了一个GITHUB上的开源项目,在客户端JS的脚本编写的时候,代码中多次使用了IIFE. 一开始我是懵逼的,不知道这种函数的意义何在,小菜鸟嘛. 后面我去研究了一番.发现了它的主要作用就是:让 ...
- 立即执行函数表达式(IIFE)
原文地址:benalman.com/news/2010/11/immediately-invoked-function-expression/ 译者:nzbin 也许你还没有注意到,我是一个对术语比较 ...
- 用lucene替代mysql读库的尝试
采用lucene对mysql中的表建索引,并替代全文检索操作. 备注:代码临时梳理很粗糙,后续修改. import java.io.File; import java.io.IOException; ...
- Notepad2替代系统自带的记事本
事情是这样的,平时我经常把一些文字复制到记事本中编辑好了再复制到目标位置,可以在系统自带的记事本中替换删除一些内容,记事本小巧,占用很少的资源,我很喜欢:但今天复制的内容中有很多数字和一些我不想要的内 ...
- 在Wcf中应用ProtoBuf替代默认的序列化器
Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...
- 什么是IIFE
立即执行函数表达式(Immediately-invoked function expression) IIFE 我们知道,在javascript(ES5)中,是没有块级作用域的概念的.看一个例子 fo ...
随机推荐
- 引用opencv异常
1.异常AttributeError: module 'cv2.cv2' has no attribute 'xfeatures2d' 原因:**3.X以后OpenCv只包含部分内容,需要神经网络或者 ...
- CTF学习路线指南(附刷题练习网址)
PWN,Reverse:偏重对汇编,逆向的理解: Gypto:偏重对数学,算法的深入学习: Web:偏重对技巧沉淀,快速搜索能力的挑战: Mic:则更为复杂,所有与计算机安全挑战有关的都算在其中 常规 ...
- VS项目种类GUID
在VS里新建的类库项目,在添加新建项时往往找不到模板.比如想新建一个WPF的资源词典文件,VS认为该类库项目不是WPF类型,就没有列出新建资源词典的模板.解决办法是在csproj文件的<Prop ...
- Jmeter-【JSON Extractor】-响应结果中二级key取值
一.请求返回样式 二.取chapter的值 三.查看结果
- Dart编程数据类型
编程语言最基本的特征之一是它支持的数据类型集.这些是可以用编程语言表示和操作的值的类型. Dart语言支持以下类型 数字 字符串 布尔 列表list map 数字 Dart中的数字用于表示数字文字.D ...
- zjoi 2008 树的统计——树链剖分
比较基础的一道树链剖分的题 大概还是得说说思路 树链剖分是将树剖成很多条链,比较常见的剖法是按儿子的size来剖分,剖分完后对于这课树的询问用线段树维护——比如求路径和的话——随着他们各自的链向上走, ...
- struts之ActionServlet
ActionServlet类是Struts框架的内置核心控制器组件,它继承了javax. servlet.http.HttpServlet类,Struts的启动一般从加载ActionServlet开始 ...
- delphi实现圆角窗体[转]
procedure TForm1.FormCreate(Sender: TObject); var hr :thandle; begin hr:=createroundrectrgn(1,1,widt ...
- RDBMS关系型数据库与HBase的对比
关系型数据库 结构: * 数据库以表的形式存在 * 支持FAT.NTFS.EXT.文件系统 * 使用Commit log存储日志 * 参考系统是坐标系统 * 使用主键(PK) * 支持分区 * 使用行 ...
- CSDN首页> 云计算 孙玄:解析58同城典型技术架构及演变
转:http://www.csdn.net/article/2015-04-09/2824437 在UPYUN主办的“UPYUN Open Talk”第三期北京站上,58同城系统架构师孙玄详细介绍了5 ...