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 相关文章推荐
jquery下将选择的checkbox的id组成字符串的方法
Nov 28 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
Apr 22 Javascript
JS自动倒计时30秒后按钮才可用(两种场景)
Aug 31 Javascript
js+ajax实现获取文件大小的方法
Dec 08 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
Nov 26 Javascript
使用Bootstrap Tabs选项卡Ajax加载数据实现
Dec 23 Javascript
jQuery实现可移动选项的左右下拉列表示例
Dec 26 Javascript
javascript十六进制数字和ASCII字符之间的转换方法
Dec 27 Javascript
JS实现多级菜单中当前菜单不随页面跳转样式而发生变化
May 30 Javascript
对Vue table 动态表格td可编辑的方法详解
Aug 28 Javascript
vue2和vue3的v-if与v-for优先级对比学习
Oct 10 Javascript
vue项目页面嵌入代码块vue-prism-editor的实现
Oct 30 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禁止页面缓存的代码
2011/10/23 PHP
360通用php防护代码(使用操作详解)
2013/06/18 PHP
thinkphp的URL路由规则与配置实例
2014/11/26 PHP
php 5.6版本中编写一个PHP扩展的简单示例
2015/01/20 PHP
js操作iframe兼容各种主流浏览器示例代码
2013/07/22 Javascript
浅谈 jQuery 事件源码定位问题
2014/06/18 Javascript
js控制一个按钮是否可点击(可使用)disabled的实例
2017/02/14 Javascript
微信小程序 chooseImage选择图片或者拍照
2017/04/07 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
利用JS测试目标网站的打开响应速度
2017/12/01 Javascript
javascript中的隐式调用
2018/02/10 Javascript
红黑树的插入详解及Javascript实现方法示例
2018/03/26 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
2018/12/02 Javascript
jQuery实现的隔行变色功能【案例】
2019/02/18 jQuery
vue 解决文本框被键盘遮住的问题
2019/11/06 Javascript
[43:51]2014 DOTA2国际邀请赛中国区预选赛 Dream Times VS TongFu
2014/05/22 DOTA
python实现逆波兰计算表达式实例详解
2015/05/06 Python
python中for语句简单遍历数据的方法
2015/05/07 Python
用Python写一个无界面的2048小游戏
2016/05/24 Python
Python实现简单网页图片抓取完整代码实例
2017/12/15 Python
numpy使用fromstring创建矩阵的实例
2018/06/15 Python
Django 使用easy_thumbnails压缩上传的图片方法
2019/07/26 Python
Python基础教程(一)——Windows搭建开发Python开发环境
2020/07/20 Python
Python 多进程、多线程效率对比
2020/11/19 Python
荷兰之家英文站:Holland at Home
2016/10/26 全球购物
全球第二大家装零售商:Lowe’s
2018/01/13 全球购物
《小石潭记》教学反思
2014/02/13 职场文书
幼儿园毕业园长感言
2014/02/24 职场文书
中国梦演讲稿5分钟
2014/08/19 职场文书
职业生涯规划书怎么写?
2014/09/14 职场文书
财务总监岗位职责范本
2015/04/03 职场文书
2015年信息宣传工作总结
2015/05/26 职场文书
redis的list数据类型相关命令介绍及使用
2022/01/18 Redis
iSCSI服务器CHAP双向认证配置
2022/04/01 Servers
CSS控制继承中的height能变为可继承吗
2022/06/10 HTML / CSS