1、闭包的定义:闭包就是能够读取其他函数内部变量的函数。在js中,可以将闭包理解成“函数中的函数。
但凡是内部的函数被保存到了外部,生成闭包。内部函数会保存外部函数的成果。闭包会导致原有作用域链不释放,造成内存泄漏(过多占用内存资源)
例子1
function a(){
function b() {
var bbb = 234;
console.log(aaa);
}
var aaa = 123;
return b;//里面的函数b被保存到了外面
}
var glob = 100;
var demo = a();//a执行的结果---b
demo();
例子2
function a(){
var num = 100;
function b (){
num ++;
console.log(num);
}
return b;//把b扔到demo里面去,b()是a的最后一条语句被执行完a函数就被执行完了,
//b在这里拿到了a的执行期上下文
//如果b在这里就执行,b(),那么生成不了闭包
}
var demo = a();//demo()和b()是一样的,名称不同
demo();//101
demo();//102
第一次aAO {num : 101}----
闭包的作用
1、实现公有变量------eg: 函数累加器
例子
function add(){
var count = 0;
function demo(){
count++;
console.log(count);
}
return demo;
}
var counter = add();//add执行结果demo
counter();
counter();
counter();
counter();
counter();
counter();
----------打印123456
2、可以做缓存(存储结构)----eg:eater
例子
function test(){
var num = 100;
function a(){
num ++;
console.log(num);
}
function b(){
num --;
console.log(num);
}
return[a,b];
}
var myArr = test();
myArr[0]();//函数a===101
// a doing a.[[scope]] 0 : aAO
// 1 : testAO
// 2 : GO
myArr[1]();//函数b===100 //a,b是并集,共用一个test的AO,-----有执行顺序
b doing b.[[scope]] 0 : aAO
1 : testAO (是a执行后改变过值基础上再操作的)
2 : GO
例子
function eater(){
var food = "";
var obj = {
eat : function(){
console.log("i am eating" + food);
food = "";
},
push : function(myFood) {
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push("banana")
eater1.eat();
// 例子2
function test(){
var food = "apple";
var obj = {
eatFood : function(){
if(food != ""){
console.log("i am eating " + food);
food = "";
} else{
console.log("There is empty!")
}
},
pushFood : function(myFood) {
food = myFood;
}
}
return obj;
}
var person = test();
person.eatFood();
person.eatFood();
person.pushFood("banana");
person.eatFood();
3、可以实现封装,属性私有化----eg:Person();
4、模块化开发,防止污染全局变量
立即执行函数
(只想执行一次,和函数其余的地方都一样,除了执行完立即被销毁,释放内存) 针对初始化功能的函数
别人的总结:(函数表达式后加上()可以被直接调用,但是把整个声明式函数用()包起来的话,则会被编译器认为是函数表达式,从而可以用()来直接调用,如(function test(){...})(),
但是如果这个括号加在声明式函数后面,如function test(){...}(),则会报错,不符合js的语法,所以想要通过浏览器的语法检查,就必须加点符号,比如()、+、!等)
表达式1:(function(){}() );建议这种
表达式2:(function(){}) ();
例子1
(function abc(a,b,c){
var a = 123;
var b = 234;
console.log(a + b +c*2);
}(1,2,3))
例子1
var num = (function(a,b,c){//num=7
var d = a + b + c*2 - 2;
return d;//有返回值
}(1,2,3));///num=7
只有表达式才能被执行符号执行
// (function test(){})函数声明被包起来变成了函数表达式,就可以被执行了,//大括号是执行符
例子1
function test(){
var a = 123;
}
test();------------test()就是一个表达式,可以调用函数
例子2
var test = function(){
console.log("a");
}()//-------------**函数表达式可以被执行**var test调用函数
例子3-----只有函数声明,不能执行
function test(){
var a = 123;
}() //--------------**函数声明,不能执行**
能被执行符号()执行的表达式,函数名字就会被自动忽略
例子4
var test = function(){
console.log("a");
}();//加上执行符号的(test:undefined)表达式自动放弃函数名称,成了立即执行函数
//这里test=undefined,取决于后面的值类型,等号=后面是一个表达式,前面的是变量声明,在执行时会放弃函数储存到test里面的引用,让test回归到被声明的状态
例子5--//加上+号/负号-/!算可执行表达式,转化成数字,被执行但乘号*和➗/不行
+ function test(){
console.log("a");
}();
例子
(function (){
console.log("a");
}())//括号是执行符,先执行最外面的括号,只有外面是数学运算的小括号,里面的括号有语法意义,把里面变成表达式,被里面执行
例子
function test(a,b,c,d) {
console.log(a+b+c+d);
}(1,2,3,4)//执行符号里面有东西就不是执行符号,而是分开,逗号,也算语法,不报错,不执行
(1,2,3,4)//系统理解在下面