JavaScript匿名、具名函数与立即执行函数IIFE详解
来源:互联网 发布:ubuntu jdk 1.8 编辑:程序博客网 时间:2024/05/21 09:37
JavaScript中的函数作用域的存在就是为了把变量和函数“隐藏”起来
符合我们的最小特权原则
同时它的另一个好处是可以避免同名标识符的冲突
今天主要来谈谈这个立即执行函数
在此之前的复习一下匿名函数与具名函数
匿名函数与具名函数
无论是匿名还是具名,都是针对函数表达式来说的
函数声明那就必须得有名字了,否则会报错的
function foo(){ //函数声明 //...}
这里我解释一个彩蛋,可能大家看我写文章的时候示例代码总是喜欢用一些
fn、func、demo、foo、bar、foobar之类的词
fn、func就是function“函数”的缩写
demo就是单词demonstration“示例”的缩写
foo、bar、foobar我们经常能够在技术书籍还有计算机文献中看到
foo是fu的变体,fuck-up缩写,意思是“一团糟”
bar是“beyond all recognition”,意思是“超越认知”,通俗说“识别不了,一塌糊涂”
就是一些占位词,相当于我们的小明小红、甲乙丙丁、张三李四…
函数表达式是可以有名字,也可以没有名字的
var foo = function(){...};console.log(foo.name); //foovar bar = function foobar(){...};//不要这么写console.log(bar.name); //foobar
可以看到第二种写法只是单纯地改变了函数的name属性
除此之外百无一用,我们不要这么写
除此之外我们最常见的用法就是函数表达式作为回调参数了
比如说在定时器中
setTimeout(function(){ //...},1000);
这里我写了匿名函数表达式
它用起来简单粗暴
但有几个缺点
- 追踪栈中没函数名,调试困难
- 如果需要引用自身,只能用arguments.callee(ES5严格模式禁用)
- 降低了函数可读性、可理解性
我们在解除事件绑定时,也需要函数名(如果不是用onclick等等直接绑定的话)
所以
给函数表达式一个名字是一个最佳实践,是一个好习惯
setTimeout(function timerHandler(){ //...},1000);
立即执行函数常用用法
立即执行函数,我习惯这么叫
也有叫自执行函数、自动执行函数什么的
说的更标准一些
立即执行函数表达式
注意我的用词,是函数表达式
它并不是什么语法
而是大家用着用着发现还能这么用
于是就流传开来,直到现在
顾名思义,就是执行流运行到这个函数就立刻执行了
社区给它规定了术语:IIFE(Immediately Invoked Function Expression)
我们常用的用法是:
(function(){ //...}());
(function(){ //...})();
我们用IIFE的时候一般都是使用一个匿名函数表达式
当然你加上名字也不错,同时拥有了具名函数表达式的优点
两种用法完全等价,使用哪种由你决定
但我更愿意把括号写在外面,感觉看着比较舒服
而且看到很多大神也和我一样
立即执行函数进阶用法
稍微进阶的用法就是在立即执行函数中传递参数
比如说我们常见的传递window
var a = '全局';(function IIFE(global){ var a = '局部'; console.log(a);// "局部" console.log(global.a);// "全局"})(window);
传window有什么好处呢?
从我们作用域的角度分析
(可以看看我写的作用域->传送门)
全局对象的引用缓存到了局部环境
这样我们可以更快的访问到全局对象,不用再跳到顶级作用域查找
这点小优化不是重点
重点的压缩代码的时候可以进行优化
也许上面的代码压缩工具可以压缩成这样
var a = '全局';(function IIFE(g){ var a = '局部'; console.log(a);// "局部" console.log(g.a);// "全局"})(window);
当代码非常大的时候,可不要小看这优化
立即执行函数变化用法
IIFE还有一种变式,你一定见过
(function IIFE(demo){ demo(window);})(function demo(global){ //...});
这种把要运行的函数放进参数的模式看起来很麻烦
但却被广泛使用,jQuery等框架整体架构也和这个很像
如果看习惯了,就会感觉它比我们传统的使用方法更容易理解
整体的函数表达式定义在IIFE第二部分,作为参数传递进IIFE第一部分
然后调用了这个函数,并且把window作为参数传入
立即执行函数的理解
立即执行函数为什么能够自动执行?
(function(){ //...})();
为什么function(){}()
这样写不可以
因为这是函数声明,函数声明是不可以执行的
只有表达式才能够执行
var demo = function(){ console.log(1);// 1 return 123;}();console.log(demo);// 123
这就是一个表达式,所以可以被执行
demo得到的是函数的返回值
既然表达式可以被执行,那么以下方式都可以被立即执行
+function(){ console.log(1);// 1}();-function(){ console.log(2);// 2}();!function(){ console.log(3);// 3}(),function(){ console.log(4);// 4}();
可以看出甚至是逗号,都可以它们变成函数表达式,然后立刻执行
不过我们千万不要这么写
如果函数有返回值的话,可能会产生意想不到的副作用
并且可读性也不好
总结
- 函数声明必须有名字
- 具名函数表达式是一个最佳实践
- 立即执行函数表达式用法:
(function(){}());
(function(){})();
- 立即执行函数传递window参数优化在作用域链查找window速度,有利于压缩代码
- 只有表达式才能够被执行
==主页传送门==
- JavaScript匿名、具名函数与立即执行函数IIFE详解
- 详解javascript立即执行函数表达式(IIFE)
- 详解javascript立即执行函数表达式(IIFE)
- 详解javascript立即执行函数表达式(IIFE)
- javascript模块化编程-详解立即执行函数表达式IIFE
- 详解javascript立即执行函数表达式(IIFE)
- 立即执行函数IIFE
- IIFE--立即执行函数
- JavaScript立即执行函数表达式(IIFE)
- javascript立即执行函数表达式(IIFE)
- 关于立即执行函数IIFE
- IIFE 立即执行函数表达式
- 立即执行函数表达式IIFE
- 【WEB开发】JavaScript中的立即执行函数表达式(IIFE)
- javascript中的立即执行函数表达式(IIFE)
- 立即执行函数(IIFE)的理解与运用
- 匿名函数与立即执行函数
- 立即执行函数表达式(IIFE )
- Unity3D插件之NGUI-Font Maker显示FreeType.dylib is missing问题解决
- Samba 学习第一章 安装与基础配置
- Android的Binder机制
- 奇怪的贸易
- 读入优化
- JavaScript匿名、具名函数与立即执行函数IIFE详解
- Android网速实时显示
- warning C4018: “<”: 有符号/无符号不匹配
- yolo-darknet配置安装与测试
- 思科VPP源码分析(多线程支持分析)
- jsoncpp Linux下编译及使用
- 从本Activity调到本Activity的方法
- Java多态性理解
- 建造者模式(Java)