举例说明什么是IIFEs?它有什么好处?
-
Instantly Invoked Function Expression 即时调用函数表达式
示例
;(function () { // ... statements return ... )()
- 最好在 IIFE 前追加分号
;
来避免解析时与前一个表达式合并出现问题
好处
- 创建一个局部作用域隔离变量;但在 ES6 拥有了块级作用域后变得没有必要,可以用语句块
{ ... }
配合let
/const
替代 - 将运行逻辑转化为可求值的表达式,弥补 JavaScript 基本逻辑语句不是表达式的缺陷
- e.g.
基本等价于
const a = (() => { if (...) return 1 else return 0 })()
let a if (...) a = 1 else a = 0
- e.g.
- 最好在 IIFE 前追加分号
-
在v8引擎架构里,对于top-level 的代码会做 pre-parsing 来检测是否有语法错误。然而这是一种性能浪费,应为在full-parsing 的时候遇到语法错误自然会抛错。 所以V8 提供了一种hack方式就是IIFE,绕过对top-level代码的 pre-parsing
-
可以使用+ - = !符号将匿名函数或函数声明转为函数表达式
eg:! function () { console.log(window) }(window);
-
自执行匿名函数,我一般用它来 1. 独立作用域,2. 直接递归,3. 节约变量
// 我经常这样子来写异步递归,不用单写函数和变量然后调用 (function loop(min, max) { if (++min > max) return; // ...... loop(min, max); }(1, 10);
// 还有更多节约变量的方式 var getInfo = (function() { var info = null; return function(callback) { if (info) callback(); ajax(api, function(res){ info = res.data; callback(); }); } })();
-
含义
IIFE: 立即执行函数
写法:
(function(){ var name = 'shaw'; })()
好处
1.在
let、const
块级作用域未出来时,我们常常会写出这样的代码for (var i=0;i<10;i++) { (function(i){ setTimeout(function(){ console.log(i); }, 100*i); })(i) }
通过立即执行函数来创造一个新的作用域并缓存变量,来解决闭包带来的副作用问题
2.模块化
由于立即执行函数,不污染外部作用域的原则,因此诞生了umd模块的写法。一般主流的框架都会提供umd格式的js,通过script标签注入页面后会生成唯一一个全局变量,内部变量都不会暴露出来
-
立即执行函数为什么可以立即执行?
- 必须是函数表达式
- 写完后要立即调用()
而(),! ?;等符号就会把函数声明语句转换成函数表达式