【JS基础】立即执行函数表达式(自执行函数)

立即执行函数表达式

立即执行函数表达式,大部分人也称为自执行函数。
在这里插入图片描述

自执行函数的写法
匿名函数
(function() {
  console.log(2)
})()
具名函数
(function log() {
  console.log(2)
})
自执行函数的传参
(function add(a, b) {
  console.log(a + b)
})(1, 2)
返回值
let fn = (function add(a, b) {
  return a + b;
}) (2, 4)

console.log(fn)
自执行函数也可以传递函数作为参数
var a =2;

(function log(fn) {
  fn(window)
})(function fn(global) {
  var a = 3;
  console.log(a); // 3
  console.log(global.a); // 2
})

在这里插入图片描述

立即执行函数有什么用?

只有一个作用:创建一个独立的作用域。

这个作用域里面的变量,外面访问不到(即避免「变量污染」)。

以一个著名的面试题为例:

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
  liList[i].onclick = function(){
    alert(i) // 为什么 alert 出来的总是 6,而不是 0、1、2、3、4、5
  }
}

为什么 alert 的总是 6 呢,因为 i 是贯穿整个作用域的,而不是给每个 li 分配了一个 i,如下:

在这里插入图片描述
那么怎么解决这个问题呢?用立即执行函数给每个 li 创造一个独立作用域即可(当然还有其他办法):

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
  !function(ii){
    liList[ii].onclick = function(){
      alert(ii) // 0、1、2、3、4、5
    }
  }(i)
}

在这里插入图片描述
在这里插入图片描述
在立即执行函数执行的时候,i 的值被赋值给 ii,此后 ii 的值一直不变。

i 的值从 0 变化到 5,对应 6 个立即执行函数,这 6 个立即执行函数里面的 ii 「分别」是 0、1、2、3、4、5。

为什么还要用另一对括号把匿名函数包起来呢?

其实是为了兼容 JS 的语法。

如果我们不加另一对括号,直接写成👇

function (){alert('我是匿名函数')}()
function a(){alert('我是匿名函数')}()

在这里插入图片描述

浏览器会报语法错误。想要通过浏览器的语法检查,必须加点小东西,比如下面几种

(function(){alert('我是匿名函数')} ()) // 用括号把整个表达式包起来
(function(){alert('我是匿名函数')}) () //用括号把函数包起来
!function(){alert('我是匿名函数')}() // 求反,我们不在意值是多少,只想通过语法检查。
+function(){alert('我是匿名函数')}()
-function(){alert('我是匿名函数')}()
~function(){alert('我是匿名函数')}()
void function(){alert('我是匿名函数')}()
new function(){alert('我是匿名函数')}()
注意事项

虽说javaScript的分号是可有可无的,但有些时候还是必要的。

console.log(5)

(function add(a, b){
	var c = 2;
	console.log(a + b);
})(1,2)

上面代码会报错,因为javaScript确实是有分号这个规则的,代表着语句的结束。

这种时候加个分号就行了

console.log(5);

(function add(a, b){
	var c = 2;
	console.log(a + b);
})(1,2)

但是很多时候我们已经习惯不加分号了,显得比较麻烦,这种时候就要知道,什么情况下该加分号。

只要语句开头是括号,方括号,正则开头的斜杠,加号,减号的情况下,在前面加分号就行了,当然也可以加别的符号,比如感叹号,不过一般都是加分号

console.log(5)

;(function add(a, b){
	var c = 2;
	console.log(a + b);
})(1,2)

!(function add(a, b){
	console.log(a * b);
})(3,2)
在对象里使用自执行函数
var a = 5
var obj = {
	a: 1,
	b: (function(){
		console.log(this.a)// 5
	})(),
	c: 4
}

在这里插入图片描述

var a = 5
var obj = {
	a: 1,
	b: +function(){
		console.log(this.a)// 5
	}(),
	c: 4
}

在这里插入图片描述
以上两种都可以,但需要注意的是对象里的立即执行表达式改变了原本this的指向,这时的thiswindow

var a = 5
var obj = {
	a: 1,
	b: function(){
		console.log(this.a)// 1
	},
	c: 4
}
obj.b()

这种时候,this是指向obj

参考下面博客:
https://www.cnblogs.com/mafeifan/p/5881408.html
https://www.cnblogs.com/tourey-fatty/p/12114649.html

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值