haizlin/fe-interview

[js] 第79天 举例说明什么是IIFEs?它有什么好处?

Opened this issue · 9 comments

第79天 举例说明什么是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

在v8引擎架构里,对于top-level 的代码会做 pre-parsing 来检测是否有语法错误。然而这是一种性能浪费,应为在full-parsing 的时候遇到语法错误自然会抛错。 所以V8 提供了一种hack方式就是IIFE,绕过对top-level代码的 pre-parsing

可以使用+ - = !符号将匿名函数或函数声明转为函数表达式
eg:

! function () {
            console.log(window)
        }(window);

1.创建局部作用域,避免全局污染

自执行匿名函数,我一般用它来 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标签注入页面后会生成唯一一个全局变量,内部变量都不会暴露出来

立即执行函数为什么可以立即执行?

  1. 必须是函数表达式
  2. 写完后要立即调用()

而(),! ?;等符号就会把函数声明语句转换成函数表达式

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

IIFES: 自执行函数, 创建局部作用域,避免全局污染。
var obj = (function(){
return {}
}())