侧边栏壁纸
  • 累计撰写 225 篇文章
  • 累计创建 275 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

立即执行函数表达式(IIFE )

DGF
DGF
2017-09-05 / 0 评论 / 0 点赞 / 27 阅读 / 0 字

在 jQuery 及其插件中经常看到如下的写法:

+function($) {}(window.jQuery);

这种写法称为:

IIFEImmediately Invoked Function Expression 立即执行的函数表达式)。

函数表达式与函数声明

函数表达式 Function Expression:

var test = function() {};

函数声明 Function Declaration:

function test() {};

函数表达式中的函数可以为匿名函数,也可以有函数名,但该函数实际上不能直接使用,只能通过表达式左边的变量 fl 来调用:

var fl = function() {
    console.log("Function expression");
};
var cc = new fl();

函数声明时必须有函数名:

function fl() {
    console.log("Function Declaration");
}
fl();

匿名函数在 console 下会报错。console 的执行和报错如下:

SyntaxError: Unexpected token (

通过一元操作符 + 变成了函数表达式。也可以使用 -~! 等其他一元运算符或者括号,目的是为了引导解析器,指明运算符附近是一个表达式。以下是三种经典方式:

+function() {};
(function() {});
void function() {};

函数表达式通过末尾的 () 来调用并运行,就是一个 IIFE。

+function() {} ();
(function() {}) ();

为了避免 $ 与其他库或者模板声明冲突,window.jQuery 作为参数传递:

+function($) {

}(window.jquery);

使用 IIFE 的好处

  1. 减少作用域查找
    使用 IIFE 的一个微小的性能优势是通过匿名函数的参数传递常用全局对象 windowdocumentjQuery,在作用域内引用这些全局对象。

    JavaScript 解释器首先在作用域内查找属性,然后一直沿着链向上查找,直到全局范围。将全局对象放在 IIFE 作用域内提升 JavaScript 解释器的查找速度和性能:

    function(window, document, $) {
    
    }(window, document, window.jQuery);
    
  2. 有利于压缩
    另一个微小的优势是有利于代码压缩。既然通过参数传递了这些全局对象,压缩的时候可以将这些全局对象匿名为一个字符的变量名(只要这个字符没有被其他变量使用过)。

    如果上面的代码压缩后会变成这样:

    function(w, d, $) {
    
    }(window, document, window.jQuery);
    
  3. 避免全局命名冲突
    当使用 jQuery 的时候,全局的 window.jQuery 对象作为一个参数传递给 $,在匿名函数内部再也不需要担心 $ 和其他库或者模板声明冲突。

  4. 通过传参的方式,可以灵活地加载第三方插件
    举个例子,如果 a.html 页面需要使用 KindEditor:

    $(function() {  
        var editor;
        KindEditor.ready(function(K) {  
            editor = K.create('textarea[data-name="kindeditor"]', {  
                resizeType: 1  
            });  
        });    
    });
    

    如果 b.html 不需要使用 KindEditor,没有引入 kindeditor.js,在合并 JS 代码后,b.html 页面会报错:

    Uncaught ReferenceError: KindEditor is not defined
    

    修改 a.js,将 KindEditor 变量参数化,通过给立即执行的函数表示式的参数赋值:

    +function(KindEditor) {
        var editor;
        if (KindEditor) {
            KindEditor.ready(function(K) {  
                editor = K.create('textarea[data-name="kindeditor"]', {  
                    resizeType: 1  
                });  
            });
        }
    }(KindEditor || undefined);
    

IIFE 的可读性问题

反对使用 IIFE 的其中一个理由是可读性差。如果有大量的 JavaScript 代码都在一段 IIFE 里,想查找 IIFE 传递的实际参数值,必须滚动到代码最后。

更可读的模式:

(function(library) {
    library(window, document, window.jQuery);
}(function(window, document, $) {

}));

jQuery 优化

大部分项目用这段代码做作用域,在 DOM 加载完成时初始化 jQuery 代码:

$(function() {});
// 等价于
$(document).ready(function() {
    // 在 DOM 加载完成时初始化 jQuery 代码。
});

区别于:

$(window).load(function() {
    // 在图片等媒体文件加载完成时,初始化 jQuery 代码。
});

结合 IIFE 的最佳实践:

+function() {
    $(function() {

    });
}(window.jQuery);

更好的写法:

+function(yourcode) {
    yourcode(window.jquery, window, document);
}(function($, window, document) {
    $(function() {

    });
});
0

评论区