likes
comments
collection
share

浅析立即执行函数

作者站长头像
站长
· 阅读数 56

一、是什么

立即执行函数又名[[IIFE]],具体对于它的介绍可以看我之前的文章。

和它相对应的是[[具名函数表达式]],是相对的。先来看看具名函数表达式:

function foo() {
  console.log('橘子哥')
}

而IIFE的典型例子如下:

;(function() {
  console.log('橘子哥')
}())

有三个不同:

  1. [[IIFE]]没有函数名,具名函数有,可以通过console.log(foo.name)打印出来
  2. [[IIFE]]直接调用,这就是它立即的由来,而具名需要添加foo()才能够运行
  3. [[IIFE]]第一个字符是;

二、IIFE给出我们带来了什么

  1. 戳破了形成[[闭包]]需要函数嵌套的谣言

创建一个独立的作用域,让我知道函数嵌套函数的目的是什么,详见上一篇文章

  1. 解决了循环打印的问题

经典面试题:

for(var i = 0; i < 5; i++) {
  setTimout(function(){
    console.log(i) // 为啥打印出来额都是5呀,而不是0 ,1 ,2 ,3, 4
  })
}

或者

var lis = ul.querySelector('li') 
for(var i = 0; i < 6; i++) { 
  lis[i].onclick = function() {
    console.log(i) // 为啥打印出来额都是5呀,而不是0 ,1 ,2 ,3, 4
  }
}

两个例子都是一个问题。i相对于函数是全局变量,所以不管循环多少个函数,里面的i指向的都是同一个内存,而这个内存中放的值只有一个。所以它们打印出来的值自然都是一样的。

要解决这个问题,自然就是让这些函数能够执行不同的i。所以函数作用域就能够办到这件事情。

for(var i = 0; i < 5; i++) {
  !function foo(j) {
     setTimout(function(){
      console.log(j) // 为啥打印出来额都是5呀,而不是0 ,1 ,2 ,3, 4
    })
  }(j)
}
var lis = ul.querySelector('li') 
for(var i = 0; i < 6; i++) { 
   !function foo(j) {
	  lis[j].onclick = function() {
	    console.log(j) // 为啥打印出来额都是5呀,而不是0 ,1 ,2 ,3, 4
	  }
  }(j)
}

ES6之前JS原生又不提供块级作用域,所以只能用[[函数作用域]]模拟了。现在处理这样的问题,[[let]]显然是更加方便的。

总结一下:

  1. 改变变量的作用域(创建一个独立的作用域)

  2. 封装临时变量。

三、一些少为人知的技巧

写上函数名, 两个作用:

第一个,辅助定位BUG。有小面这串代码:

!function(){
  a
  console.log(11)
}()

明显看出其中a没有定义,会在控制台把如下错误。

浅析立即执行函数

如果我们给它添加上函数名,会有什么不一样的么?

!function foo() {
  a
  console.log(11)
}()

报错信息就会出现foo函数名。这就是为啥说它可以辅助定位BUG。

浅析立即执行函数

第二个,老一代框架写法, 比如说JQ:

;(function JQ(g){
  g(window)
}(function g(window){
  // code
}))

了解一下即可。

转载自:https://juejin.cn/post/7197424168622473271
评论
请登录