考题:
一、闭包:被包裹在其他函数中的函数,叫闭包(常用定义)父函数 包裹了子函数,子函数使用了父函数的变量/参数,导致这个变量和参数不会被回收,闭包就产生了
/父作用域 包裹了子作用域,子作用域使用了父作用域的变量/参数,闭包就产生了
注意:先有作用域才有闭包,并且是同一个作用域才有影响,不然独立的作用域是互不影响的
例如
闭包产生的原理:
二、闭包的特点
需提及:变量回收机制
变量为什么会回收?因为变量是一直存在内存里面的
变量回收的特点:全局的变量是不会被回收(除非关闭当前网页的时候才会回收)
例如:let x=10;//全局变量
例如:局部变量 function fn(){ let a=10;
console.log(a);//a(局部变量)使用完了之后就会被垃圾回收机制回收,目的节省资源,释放存储空间 } fn();
考题:
闭包特点(作用):如果需要局部变量不要被回收,就使用闭包,缺点:会占内存,不会影响运转速度,因为不会被回收,所以不到万不得已就不要使用闭包
注意:并不是只有函数才有作用域
例如1:
i是打印推出循环时的值为5
例如2
补充:函数在哪儿定义,作用域就在哪儿,同一个函数多次执行,作用域互不影响(产生的作用域不同)
打印:undefined和3,因为var变量提升;
打印:10 11 10 11 12
建议使用this的原因,在闭包中可以使得父级变量回收
注意:开发中尽量使用let来定义变量
补充:.var的奇怪处理与let的好处
1)var奇怪的处理
var只会在function里面能够产生作用域,其余的都不会当成作用域
例如:
console.log(a);//打印undefined,不会报错
if(false){
var a=10;//if里面的不是作用域,所以var的a会被提前解析到全局作用域/var不会把if看作一个作用域,所以var会被提前解析,但是由于判断是假,所以a=10无效
};
console.log(a);//打印undefined,不会报错
//在for里面同理
if(false){
function b(){}
}
console.log(b);//undefined function规定
//以后会使用babel工具把ES6的代码转换成ES5
var与let在for中的区别
例如
//let会把for的小括号当成一个单独的子作用域,i不是全局变量
for(let j=0;j<10;j++){
console.log(j);//0-9
}
console.log(j);//报错,因为for里面的let会解析成一个局部作用域
//var不会把for的小括号当成一个作用域,所以相当于全局变量,在function是局部变量
for(var i=0;i<10;i++){
console.log(i);//0-9
}
console.log(i);//10因为var会被提前解析,而且是全局变量
2)let的好处
好处之一:符合程序员的书写格式(没有定义的变量不能提前试用,符合逻辑)
例如:console.log(a);//报错 let a=10;
好处之二:同一个作用域不可以let同一个变量
let x=9; let x=2;//报错
好处之三:let 不仅仅会把函数当成作用域,if for…中的let都会把他们当成一个单独的作用域
if(false){ let x=2; } console.log(j);//报错
并且let不会污染全局