前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript立即执行函数(IIFE)的使用

JavaScript立即执行函数(IIFE)的使用

作者头像
OECOM
发布2020-07-01 17:41:42
2.2K0
发布2020-07-01 17:41:42
举报
文章被收录于专栏:OECOMOECOM

js的立即执行函数(IIFE)有两种写法,分别为:(function ( ){})( ) 与 (function ( ){}( )) ,这两种写法基本上是没有区别的。

那么为什么要 IIFE?

1.传统的方法啰嗦,定义和执行分开写;

2.传统的方法直接污染全局命名空间(浏览器里的 global 对象,如 window)

函数范围与块范围界定

使用var关键字声明的局部变量的作用域为封闭函数。如果不存在这样的函数,则会将变量创建为全局变量,从而污染全局范围。为了防止这种情况,我们可以使用一个IIFE为局部变量创建一个函数包装器:

代码语言:javascript
复制
(function() {
    var foo = "bar";
    console.log(foo);
})();

foo; // ReferenceError: foo is not defined

现在的论点是,不使用IIFE,我们可以使用块范围变量来获得相同的结果。ECMAScript 2015引入的关键字letconst关键字声明局限于封闭而不是封闭函数的局部变量:

代码语言:javascript
复制
{
    let foo = "bar";
    console.log(foo);
}

foo; // ReferenceError: foo is not defined

但是,块范围变量不能替代立即调用的函数表达式。是的,let并且const可用于局部变量的可见性限制对周边块-如果2015年的ECMAScript支持,那就是!

但是,如果您在尚不支持ECMAScript 2015的环境中运行JavaScript代码(例如旧版浏览器),则不能使用新建letconst关键字来创建块范围的本地变量。在这种情况下,您将不得不求助于经典函数范围。

闭包和私人数据

IIFE的另一个用例是围绕由IIFE返回的函数访问的局部变量提供包装范围。通过这种方式,即使函数在IIFE的词法范围执行,也会创建一个闭包,使函数能够访问局部变量。

假设我们要创建一个函数uniqueId,每次调用它时都会返回一个唯一标识符(如“id_1”,“id_2”等)。在IIFE中,我们将跟踪每次调用计数器函数时递增的私有计数器变量。我们从IIFE返回另一个函数,该函数在调用时返回一个新的标识符字符串:

代码语言:javascript
复制
const uniqueId = (function() {
    let count = 0;
    return function() {
        ++count;
        return `id_${count}`;//这里使用了模板字符串 
    };
})();

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

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

代码语言:javascript
复制
const counter = (function() {
    let counterValue = 0;  

    return {
        increment() {
            ++counterValue;  
        },  

        get value() {
            return counterValue;
        }
    };
})();

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

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

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

变量重命名

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

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

代码语言:javascript
复制
window.$ = function somethingElse() {

    // ...

};

 

(function($) {

    // ...

})(jQuery);

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

捕获全局对象

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

代码语言:javascript
复制
(function(global) {

    // ...

})(this);

不管是浏览器还是Node.js的环境,global参数将会指定到对的全局对象上。

压缩方面的优化

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

代码语言:javascript
复制
(function(window, document, undefined) {

    // ...

})(window, document);

一个JavaScript压缩工具例如UglifyJS可以缩短函数的参数名为单个字母的标识符

代码语言:javascript
复制
(function(w, d, u) {

    // ...

})(window, document);

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

文章参考:Use Cases for JavaScript's IIFEs

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 函数范围与块范围界定
  • 闭包和私人数据
  • 变量重命名
  • 捕获全局对象
  • 压缩方面的优化
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档