立即执行函数除了执行完就被销毁之外,与函数没有任何区别。
立即执行函数的两种写法:
(function(){}())//W3C推荐
(function(){})()
参数传递:
(function(形参) {
}(实参))
返回值:
var num = (function() {
return 123;
}())
console.log(num);//123
立即执行函数都是匿名函数,但为什么都是匿名函数呢?
要想知道为什么是匿名函数,首先要搞懂函数的定义方式
函数定义有两种:
1、函数表达式;
var demo1 = function() {
console.log('demo1');
}
2、函数声明
function demo2() {
console.log('demo2');
}
现在向这两种函数声明方式声明的函数后面都添加一个小括号会有什么变化呢?
var demo1 = function() {
console.log('demo1');
}()
我们可以发现,函数demo1被执行了,那么函数demo2会不会执行呢?
function demo2() {
console.log('demo2');
}()
运行函数demo2之后,浏览器报了一个语法错误。
为什么在函数表达式后面加括号就可以得到立即执行函数的效果,在函数声明后面加括号却被报错呢
原因是:只有表达式才能被执行符号执行(在函数后面加上的小括号就是执行符号)
既然函数demo1能被立即执行,那么再控制台输入demo1能不能被找到呢?
再输入demo1已经不能被找到了,这就是因为能被执行符号执行的函数表达式,这个函数的名字就会被忽略
那么有没有什么办法可以将demo2改造成立即执行函数呢?
其实办法有很多,正号、负号、取反(!)、void、与、非等都可以(与和非要注意逻辑顺序),加上这些符号之后将后面的函数变成了表达式,再加上执行符号函数就可以被执行了,书写如下:
+ function demo2() {
console.log('demo2');
}()
- function demo2() {
console.log('demo2');
}()
! function demo2() {
console.log('demo2');
}()
接下来我们来解析一下W3C推荐的立即执行函数的写法
(function(){
}())
最外面的小括号是运算符与正负号作用一样,将里面的函数变成了一个表达式,函数后面的小括号是执行符号。
接下来我们验证一下是否可以输出函数
(function test(){
console.log('test')
}())
就会出现 b 没有定义的现象
立即执行函数的用法:化解闭包作用域链
function a () {
var arr = [];
for(var i = 0; i<10; i++) {
arr[i] = function() {
console.log(i);
}
}
return arr;
}
let myArr = a();
for(var j = 0; j < myArr.length; j++){
myArr[j]()
}
这种输出的都是10,因为在for循环结束之后 i 的值就为10,所以在后面调用函数输出的 i 的值也都是10.
修改方法:
方法一:使用立即执行函数
function a () {
var arr = [];
for(var i = 0; i<10; i++) {
(function(j){
arr[j] = function() {
console.log(j);
}
}(i))
}
return arr;
}
let myArr = a();
myArr[0]()
方法二:在for循环的时候使用let声明,就没有变量提升
function a () {
var arr = [];
for(let i = 0; i<10; i++) {
arr[i] = function() {
console.log(i);
}
}
return arr;
}
let myArr = a();
myArr[0]()
最后还有一点就是,在使用立即执行函数的时候,要把官方推荐的两种写法写在上面,如果有符号改变函数为表达式在官方推荐前面就会报错。
如:正确写法不报错
(function(){}())//W3C推荐
(function(){})()
+ function demo2() {
console.log('demo2');
}()
var test = function() {
console.log('test');
}