登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP网盘
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
javascript中IIFE(立即执行函数表达式)到底是咋来的? ...
javascript中IIFE(立即执行函数表达式)到底是咋来的?
[ 复制链接 ]
澹台吉星
7 天前
介绍
IIFE(Immediately Invoked Function Expression),中文名称:立即执行函数表达式,其实IIFE最早并不叫这个名字,而是叫做Self-Executing Anonymous Function,即自执行匿名函数。根据MDN的资料,IIFE这个说法最早由Ben Alman于2010年提出,下面我们一起来看看这个名字的来龙去脉。
2010年11月5日,Ben Alman写下来他的著名文章:Immediately-Invoked Function Expression (IIFE),标志着IIFE这个名字的诞生。
在文章中,Ben Alman称他是一个对待术语非常严谨的人,之前他多次看到Self-Executing Anonymous Function这个说法,觉得不是很恰当,于是他提出了Immediately-Invoked Function Expression这个说法。
IIFE到底是咋来的?
当我们定义一个函数或者一个函数表达式时,你得到的是一个名字,通过这个名字,你就可以调用这个函数。
下面这两段代码,第一个定义了一个普通函数,第二个定义了一个函数表达式,这两种形式,我们都可以通过标识符foo来调用它们。
// 普通函数
function foo() {
console.log('I am a function');
}
// 函数表达式
const foo = function() {
console.log('I am a function expression');
};
复制代码
也就是说,当javascript解释器遇到全局function关键字,或者一个函数内部的function关键字时,会将其解释为一个函数声明。
然而函数声明是无法直接调用的,所以下面的写法会导致错误:
function foo() {
console.log('I am a function'); // Uncaught SyntaxError: Unexpected token ')'
}();
复制代码
我们来分析一下,上面这段代码,javascript解释器会将其解释为一个函数声明,和一个分组操作符(()), 分组操作符是用来改变运算符优先级的,里面必须有表达式才行,所以javascript解释器会报错。
那我们就给它一个表达式:
function foo() {
console.log('I am a function'); // Uncaught SyntaxError: Unexpected token ')'
}(1);
复制代码
这回代码不报错了,但是这段代码毫无意义,这个函数并没有执行,实际上这段代码与下面的代码等价:
function foo() {
console.log('I am a function');
}
(1);
复制代码
它的返回值就是1,这不是我们想要的结果,我们需要函数定义后能立即被执行,那就需要我们告诉javascript解释器,这个函数是一个表达式,而不是一个声明,因为表达式可以立即执行,但是声明不能。
而在javascript中,生成表达式最简单的方式就是用()包裹起来,于是有了下面的代码
(function foo() {
console.log('I am a function');
});
复制代码
这样函数声明就变成了一个函数表达式,但是这个表达式没有名字,我们没法调用它,我们先给它一个名字,然后通过名字调用它。
const bar = (function foo() {
console.log('I am a function');
});bar(); // I am a function
复制代码
这样完全没有问题,但是这里的bar实在有点多余,实际上bar和
(function foo() {
console.log('I am a function');
});
复制代码
是等价的,既然bar()可以调用函数,那么我们直接在函数表达式末尾加上(),也可以调用这个函数,于是就有了下面的代码,这就是IIFE的由来。
(function foo() {
console.log('I am a function');
})();
复制代码
将()写在外层的括号内也一样,这种方式颇得javascript专家Douglas Crockford的青睐。我本人更喜欢第一种。
(function() {
console.log('I am a function');
}());
复制代码
IIFE的变种
由上面介绍可知,生成IIFE的精髓就是将函数声明变成函数表达式,而在javascript中,生成表达式可不止使用()包裹起来这一种方式,还有很多其他的方式可以实现。于是IIFE也就是产生了诸多变种。
这个变种利用赋值运算符=来实现,赋值运算符是将右侧表达式的值赋值给左侧变量的,所以它右侧的部分被解析成了函数表达式及其调用。
const i = function() {
console.log('I am an IIFE');
}();
复制代码
下面的表中使用逻辑运算符来生成表达式。
true & (function() {
console.log('I am an IIFE');
}());
复制代码
还有下面这些,都是利用一元运算符来生成函数表达式。
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
复制代码
最后来一个不为人知的,void运算符会对其右侧的表达是求值然后返回undefined。(void expression - 先对expression求值,然后返回undefined)。
void function() {
console.log('I am an IIFE');
}();
复制代码
还有使用new运算符来生成IIFE,这种方式比较少见,因为它会创建一个新的对象。
new function() {
console.log('I am an IIFE');
}();
复制代码
这些方式都比较偏门了,不建议使用,只是用来帮助我们理解IIFE的。
为什么Self-Executing Anonymous Function这个名字不好?
Ben Alman认为这个名字有两个问题:
Self-Executing
:这个名字暗示函数会调用自己,但是实际上函数是立即被执行的,而不是调用它自身。
比如下面的几段代码都会调用自己,但是这并不是IIFE的语义。
// 递归调用自身
function foo() { foo();
// 使用arguments.callee调用自身
const foo = function() { arguments.callee(); };
复制代码
Anonymous
:这个名字暗示函数是匿名的,但实际上函数可以有名字,也可以没有名字,比如下面的例子:
// 有名字的IIFE
(function foo() {
console.log('I am an IIFE');
})();
复制代码
参考
https://web.archive.org/web/20171201033208/http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife
大家有时间可以去拜读Ben Alman的原文,大佬写的东西就是不一样,通俗易懂,是我辈楷模!
出处:http://www.cnblogs.com/graphics/本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
澹台吉星
7 天前
关注
0
粉丝关注
12
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9986
背竽
9992
猷咎
9990
4
凶契帽
9990
5
里豳朝
9990
6
处匈跑
9990
7
黎瑞芝
9990
8
恐肩
9988
9
终秀敏
9988
10
杭环
9988
查看更多