在前端开发过程中,JS中的原理使用知识点是老生常谈,但是有时候在开发中会忽略一些细节和不经意的知识点,尤其是刚入行的新晋开发者更是一知半解,在对JS整体使用的时候会有所遗漏。那么本篇博文就来分享一下关于在JS中立即执行函数相关的对比使用总结,方便查阅使用。
声明一个函数,然后立即调用该函数,这时候的该函数就是一个立即执行函数,换句话说就是声明函数以后立即执行该函数就叫做立即执行函数,即IIFE (Immediately Invoked Function Expression)。通常立即执行函数会以匿名函数的形式来声明,匿名函数的写法格式为function(){},即使用关键字function来声明函数,且未给该函数命名,但是匿名函数不能直接单独使用,需要使用小括号()包裹起来,不然就会报错。
立即执行函数的作用大概有三个方面:
1、为了避免污染全局变量,声明函数不设置函数名;
2、通过创建一个独立的作用域,使得作用域里面的变量等内容不被作用域之外访问,避免声明的变量相互污染;
3、JS常见的一个经典知识点,闭包的实现,还有数据私有化的设置。
立即执行函数的两种写法形式,如下所示:
// 写法一:用小括号把整个函数的定义和括号调用全部包裹起来
(function(){
// 函数体
...
}())
// 写法二:用小括号只把把函的数定义包裹起来,然后后面再加括号调用
(function (){
// 函数体
...
})()
需要注意的是:使用小括号包裹是因为浏览器的JS引擎规定要求,如果function放在首行,一概解析成语句,但是在使用立即执行函数的时候需要浏览器的JS引擎把function解析为一个表达式,所以小括号包裹为的就是解决这个问题的。
这里按照一般的普通函数和匿名函数的写法做一个简单的对比,普通函数和匿名函数按顺序表示相同的作用,具体对比如下所示:
function bar(){console.log("Hello JavaScript!")}()//在声明的函数后面直接加()会报错
(function bar(){console.log("Hello JavaScript!")}())//用小括号把整个函数表达式包起来就可以正常执行
(function bar(){console.log("Hello JavaScript!")})()//用小括号把函数包起来也可以正常执行
!function bar(){console.log("Hello JavaScript!")}()//使用!取反,只为了通过JS语法检查。
+function bar(){console.log("Hello JavaScript!")}()//使用+可以正常执行,只为了通过JS语法检查。
-function bar(){console.log("Hello JavaScript!")}()//使用-可以正常执行,只为了通过JS语法检查。
~function bar(){console.log("Hello JavaScript!")}()//使用~可以正常执行,只为了通过JS语法检查。
void function bar(){console.log("Hello JavaScript!")}()//使用void可以正常执行,只为了通过JS语法检查。
new function bar(){console.log("Hello JavaScript!")}()//使用new可以正常执行,只为了通过JS语法检查。
(function(){console.log("Anonymous Function!")}())
(function(){console.log("Anonymous Function!")})()
!function(){console.log("Anonymous Function!")}()
+function(){console.log("Anonymous Function!")}()
-function(){console.log("Anonymous Function!")}()
~function(){console.log("Anonymous Function!")}()
void function(){console.log("Anonymous Function!")}()
new function(){console.log("Anonymous Function!")}()
上面普通函数和匿名函数的对比中,函数关于使用!、+、-、=等运算符,都能让它们起到立即执行的作用,使函数声明直接转换成了函数表达式,帮助浏览器的JS引擎识别它们是函数表达式,不是函数声明。
若立即执行函数里面需要使用函数外部的变量,这就需要通过使用参数传递的方式来解决。在立即执行函数内部使用的形参就是传递到函数内部的外部变量,进入立即执行函数自己的作用域,且不受外部变量的影响。具体使用场景如下所示:
(function(a){
// 使用的形参就是传递到函数内部的外部变量
console.log(a)
})(b)
立即执行函数和其他函数一样都是可以返回任意类型的值,主要是通过返回值来实现闭包的需求,具体示例如下所示:
var res = (function(){
var aaa = 123456;
return function() {
return aaa;
}
})()
// 该立即执行函数的返回值是一个函数,所以需要通过 () 来调用即可
console.log(res()) //输出结果为:123456
这里需要延伸一下,立即执行函数和闭包有一个共同优点就是能减少全局变量的使用。但是它们也有不同之处,立即执行函数只是函数的一种调用方式,在声明之后就立即执行,该类函数一般都只调用一次,而且调用完之后会立即销毁,不会占用内存;可是闭包主要让外部函数能够访问内部函数的作用域,虽然也是减少了全局变量的使用保证了内部变量的安全性,但是因被引用的内部变量不能被销毁,就增大了内存消耗,且使用不当很容易造成内存泄露。
通过上面关于立即执行函数的介绍,(function(){}())与(function(){})()的区别这个问题,是从不同角度来看的,但是从最终的结果来看,二者没啥区别,是一回事,得出该结论的依据就是(function(){}())与(function(){})()的AST是相同的,而且最后的结果都是一次性函数调用,以及最后解析器产生的结果也是一致的没啥区别,它们的功能也是相同的:创建一个函数并且立即调用执行。
最终的结果就是:(function(){}())与(function(){})()没有区别,它们是相同的,不仅可以立即执行函数,而且可以模拟块级作用域。
通过上面介绍(function(){}())与(function(){})()的区别总结,是不是彻底掌握了相关知识点以及使用原理?这个知识点很重要,不管是在实际开发过程中还是在求职面试中,都是高频知识点,所以必须要彻底掌握,尤其是对于vue初学者来讲更是要掌握,这里不再过多赘述重要性。
以上就是本章的全部内容,欢迎关注三掌柜的微信公众号“程序猿by三掌柜”,三掌柜的新浪微博“三掌柜666”,欢迎关注!
三掌柜的微信公众号:
三掌柜的新浪微博: