函数自调用与闭包(详解)
一、函数
数的定义有两种:一为函数的声明、二为函数表达式-匿名函数
函数声明
1 function fn(){//需要函数名 2 console.log("函数声明"); 3 } 4 fn()
函数表达式
1 const fs=function(){//需要定义变量接收 2 console.log("函数表达式"); 3 } 4 console.log(fs);
函数自调用
自调用的函数一般是匿名函数 也就是说自调用时是函数的表达式
错误的写法
错误一
原因是js解析时,遇到function关键字被默认当成函数声明,而不是一个函数表达式,让后面的"();"变得孤立,从而产生语法错误。函数声明需要一个函数名,上面代码中函数没有函数名。要解决的就是让function () {console.log(111);}是一个函数表达式,而不是函数声明语句。
(function{//.......}) 是表达式----加个括号 function{//.......}
当js执行到(function {// code})();时, 由于(function {// code})是表达式, js会去对它求解得到返回值, 由于返回值是一 个函数, 故而遇到();时, 便会被执行。也可以表示为如下形式
var i = function(){ return 10; }();
正确的写法
一、最前面和最后加个小括号
1 // 没有参数的情况 2 (function () { 3 console.log(111); 4 }()); 5 6 // 有参数的情况 7 (function (形参1, 形参2) { 8 // 函数体 9 }(实参1, 实参2));
二、function外面加括号
1 //没有参数的情况 2 (function () { 3 console.log(222); 4 })(); 5 6 //有参数的情况 7 (function (形参1, 形参2) { 8 //函数体 9 })(实参1, 实参2);
三、最前面和最后面加上中括号
1 //没有参数的情况 2 [function () { 3 console.log(333); 4 }()]; 5 6 //有参数的情况 7 [function (形参1, 形参2) { 8 //函数体 9 }(实参1, 实参2)];
四、function前面加运算符,常用!、-、+
1 //没有参数的情况 2 !function () { 3 console.log(444); 4 }(); 5 6 //有参数的情况 7 !function (形参1, 形参2) { 8 //函数体 9 }(实参1, 实参2);
五、function前面加void
1 //没有参数的情况 2 void function () { 3 console.log(555); 4 }(); 5 6 //有参数的情况 7 void function (形参1, 形参2) { 8 //函数体 9 }(实参1, 实参2);
闭包
大函数里装着小函数 第一次调用大函数:返回小函数 第二次调用:执行返回的小函数的内部代码
变量的作用域分全局变量和局部变量,局部变量仅在函数内部使用
闭包的核心就是内部函数可以引用外部函数的参数和变量,通过返回函数来扩大函数的作用域
闭包传递参数
定义函数如下,定义obj变量时,传入参数,当obj()调用时,输出传入的参数1 function fun(x) {//函数声明方式 2 return function() { 3 console.log(x); 4 } 5 } 6 var obj = fun(4); 7 // 相当于 obj = function() {console.log(4)} 8 obj(); //执行 console.log(4)
都是两次调用 调用(返回出内部函数)-赋值-调用(返回出的函数)
事件闭包
倘若我们需要为每一个li添加click事件,点击li出现对应的序号