js中let能否完全替代IIFE


Posted in Javascript onJune 15, 2019

前言

最近,我写了一篇关于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);

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js/ajax跨越访问-jsonp的原理和实例(javascript和jquery实现代码)
Dec 27 Javascript
select、radio表单回显功能实现避免使用jquery载入赋值
Jun 08 Javascript
浅析js预加载/延迟加载
Sep 25 Javascript
jQuery on方法传递参数示例
Dec 09 Javascript
jquery验证手机号是否正确实例讲解
Nov 17 Javascript
jQuery组件easyui对话框实现代码
Aug 25 Javascript
JS闭包与延迟求值用法示例
Dec 22 Javascript
Javascript中的 “&” 和 “|” 详解
Feb 02 Javascript
JS+canvas绘制的动态机械表动画效果
Sep 12 Javascript
vue使用axios上传文件(FormData)的方法
Apr 14 Javascript
使用vue实现多规格选择实例(SKU)
Aug 23 Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
Sep 21 Javascript
回顾Javascript React基础
Jun 15 #Javascript
详解微信小程序胶囊按钮返回|首页自定义导航栏功能
Jun 14 #Javascript
微信小程序版本自动更新的方法
Jun 14 #Javascript
vue+express+jwt持久化登录的方法
Jun 14 #Javascript
深入剖析JavaScript instanceof 运算符
Jun 14 #Javascript
ES6 Promise对象的含义和基本用法分析
Jun 14 #Javascript
ES6顶层对象、global对象实例分析
Jun 14 #Javascript
You might like
浅析php如何实现App常用的秒发功能
2016/08/03 PHP
PHP快速排序quicksort实例详解
2016/09/28 PHP
PHP 断点续传实例详解
2017/11/11 PHP
PHP长连接实现与使用方法详解
2018/02/11 PHP
laravel使用Faker数据填充的实现方法
2019/04/12 PHP
真正的JQuery.ajax传递中文参数的解决方法
2011/05/28 Javascript
jQuery写的日历(包括日历的样式及功能)
2013/04/23 Javascript
在JavaScript应用中实现延迟加载的方法
2015/06/25 Javascript
JavaScript电子时钟倒计时
2016/01/09 Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
2016/06/21 Javascript
react-native 封装选择弹出框示例(试用ios&android)
2017/07/11 Javascript
利用nvm管理多个版本的node.js与npm详解
2017/11/02 Javascript
利用JavaScript的%做隔行换色的实例
2017/11/25 Javascript
JS实现的计数排序与基数排序算法示例
2017/12/04 Javascript
基于 Immutable.js 实现撤销重做功能的实例代码
2018/03/01 Javascript
Vue退出登录时清空缓存的实现
2019/11/12 Javascript
JS原型prototype和__proto__用法实例分析
2020/03/14 Javascript
400多行Python代码实现了一个FTP服务器
2012/05/10 Python
Python标准库之随机数 (math包、random包)介绍
2014/11/25 Python
Python使用urllib2模块实现断点续传下载的方法
2015/06/17 Python
django框架基于模板 生成 excel(xls) 文件操作示例
2019/06/19 Python
Django REST framework 如何实现内置访问频率控制
2019/07/23 Python
python的scipy实现插值的示例代码
2019/11/12 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
python查看矩阵的行列号以及维数方式
2020/05/22 Python
如何利用CSS3制作3D效果文字具体实现样式
2013/05/02 HTML / CSS
HTML5之SVG 2D入门4—笔画与填充
2013/01/30 HTML / CSS
无谷物狗粮:Pooch & Mutt
2018/05/23 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
社会学专业学生职业规划书
2014/02/07 职场文书
五五普法心得体会
2014/09/04 职场文书
初中成绩单评语
2014/12/29 职场文书
go mod 安装依赖 unkown revision问题的解决方案
2021/05/06 Golang
SpringBoot整合阿里云视频点播的过程详解
2021/12/06 Java/Android
Golang流模式之grpc的四种数据流
2022/04/13 Golang
如何通过cmd 连接阿里云服务器
2022/04/18 Servers