闭包有3个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收
function outter(){
var name='dov'
function innter(){
return name;
}
return innter
}
var innter=outter();
console.log(innter())
outter()返回了一个具名函数inner,这个函数在outter()作用域内部,所以它可以获取outter()作用域下变量name的值,将这个值作为返回值赋给全局作用域下的变量innter,实现了在全局变量下获取到局部变量中的变量的值。
function fn(){
var num=3
return function(){
var n=0;
console.log(++n);
console.log(++num);
}
}
var fn1=fn();
fn1(); // 1 4
fn1(); // 1 5
一般情况下,在函数fn执行完后,就应该连同它里面的变量一同被销毁,但是在这个例子中,匿名函数作为fn的返回值被赋值给了fn1,这时候相当于fn1=function(){var n = 0 … },并且匿名函数内部引用着fn里的变量num,所以变量num无法被销毁,而变量n是每次被调用时新创建的,所以每次fn1执行完后它就把属于自己的变量连同自己一起销毁,于是乎最后就剩下孤零零的num,于是这里就产生了内存消耗的问题
for(var i=1;i<=5;i++){
setTimeout(function timer() {
console.log(i) // 6 6 6 6 6
}, 1000);
}
延时的回调函数会在循环结束时才执行。当定时器运行时即使每个迭代中执行的是 setTimeout(。。。 1000); 所有的回调函数依然是在循环结束后才会被执行,因此会每次输出一个6出来。
for(var i=1;i<=5;i++){
(function(j){
setTimeout(function timer() {
console.log(j) // 1 2 3 4 5
}, 1000);
})(i)
}
我们每次迭代时都创建一个新的作用域。
改造成下面的方式,let声明可以用来劫持快作用域
for(let i=1;i<=5;i++){
setTimeout(function timer() {
console.log(i) // 1 2 3 4 5
}, 1000);
}
for循环头部的let声明会有一个特殊的行为,这个行为支出变量在循环过程中不止被声明一次,每次迭代都会声明。随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量