JavaScript 之 立即执行函数

1、定义

​ 声明一个函数,并立即调用这个函数,此时这个函数就是立即执行函数,简单来说就是定义函数之后立即执行该函数。立即执行函数一般也写成匿名函数的形式,匿名函数写法为 function(){},就是使用function关键字声明一个函数,但是未命名的函数。关于匿名函数有一点要注意的是:匿名函数不能单独使用,否则会报错,至少需要用 () 包裹起来。

2、作用

​ ① 不需要为函数命名,避免污染全局变量。

​ ② 创建一个独立作用域,这个作用域里面的变量,外部访问不到,避免变量污染。

​ ③ 闭包和私有数据

3、使用场景

​ ① 在页面加载完成后,需要立即执行的一些初始化设置,例如时间处理,创建对象等。

​ ② 一些只需要执行一次的代码,代码中的某些变量在执行结束后,再也不会被用到,我们就不适合用全局变量,可能会变量污染,此时更适合用立即执行函数。

4、语法

// 立即执行函数的两种写法

// 第一种:用括号把整个函数定义和括号调用包裹起来
(function(){
 // 函数体
}())

// 第二种:用括号把函数定义包裹起来,后面再加括号调用
(function (){
 // 函数体
})()

// 注意:之所以要用圆括号包裹,是因为在浏览器的JS引擎规定,如果function出现在行首,一律解析成语句,
// 而此时我们希望JS引擎将其理解为一个表达式,圆括号的包裹就是起这个作用的。

5、常见写法

// 普通函数形式
function foo(){console.log("Hello World!")}()//声明函数后加()会报错
(function foo(){console.log("Hello World!")}())//用括号把整个表达式包起来,正常执行
(function foo(){console.log("Hello World!")})()//用括号把函数包起来,正常执行
!function foo(){console.log("Hello World!")}()//使用!,求反,这里只想通过语法检查。
+function foo(){console.log("Hello World!")}()//使用+,正常执行,这里只想通过语法检查。
-function foo(){console.log("Hello World!")}()//使用-,正常执行,这里只想通过语法检查。
~function foo(){console.log("Hello World!")}()//使用~,正常执行,这里只想通过语法检查。
void function foo(){console.log("Hello World!")}()//使用void,正常执行,这里只想通过语法检查。
new function foo(){console.log("Hello World!")}()//使用new,正常执行,这里只想通过语法检查。

// 匿名函数形式
(function(){console.log("我是匿名函数。")}())
(function(){console.log("我是匿名函数。")})()
!function(){console.log("我是匿名函数。")}()
+function(){console.log("我是匿名函数。")}()
-function(){console.log("我是匿名函数。")}()
~function(){console.log("我是匿名函数。")}()
void function(){console.log("我是匿名函数。")}()
new function(){console.log("我是匿名函数。")}()

6、参数传递

// 如果立即执行函数中需要用到外部变量,我们可以通过参数传递的方式,在函数内部使用
// 形参就是传递进来的外部变量,进入立即执行函数独立的作用域,不再受外部变量的影响

(function(j){
    // 使用外部变量
	console.log(j)
})(i)

7、返回值

// 跟其他函数一样,可以返回任何类型的值
// 可通过返回值实现闭包

var result = (function(){
    var num = 666;
    reutrn function() {
        return num;
    }
})()
// 由于返回值是一个函数 所以通过 () 进行调用
console.log(result())

8、常见面试题

// 1.普通流程
for(var i=0;i<3;i++) {
    setTimeout(function() {
        console.log(i)
    },300)// 输出结果为 3 3 3
}

// 2.立即执行函数
for(var i=0;i<3;i++) {
	(function (j){
		setTimeout(function (){
			console.log(j)
		},300) // 输出结果为 0 1 2
	})(i)
}

// 3.let 块级作用域
for(let i=0;i<3;i++) {
    setTimeout(function() {
        console.log(i)
    },300)// 输出结果为 0 1 2
}

​ 第一段代码中 setTimeout 定时器属于异步操作,它是在 for 循环执行完之后,才执行的,因为 i 是var 声明的,作用域贯穿于整个函数作用域,所以当执行setTimeout时,i 已经通过for循环变成了 3 ,所以输出结果为:3 3 3。

​ 第二段代码中使用了立即执行函数,使每次for循环都创建了一个独立作用域,并把每次循环 i 的值,传递进独立作用域,不受外界影响,所以输出结果为 :0 1 2。

​ 第三段代码中使用了 ES6 的 let ,使每次for循环都创建了一个块级作用域,不同作用域之间不影响,所以输出结果为: 0 1 2。

  • 17
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的小朱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值