1、垃圾回收
(1)全局变量不会被回收
(2)局部变量会被回收,函数执行结束,函数内部东西会被销毁
(3)某作用域中的某个变量还在被另一个作用域引用就不会被回收
var a=[];
for(var i = 0;i<10;i++){
var q = i;
a[i]=function(){console.log(q)}
}
a[0]();//9
首先,for循环不是一个函数作用域,因此变量a,i,q
都是同级的。其次,只是将函数赋值给a[i]
,函数并没有立即执行。for循环执行完毕后,i=10,q=9
,因此,执行a[0]()
,输出q
,q=9
。
解决方法:
(1)使用let声明变量
(2)使用闭包
(1)使用let声明变量
var a=[];
for(let i = 0;i<10;i++){
let q = i;
a[i]=function(){console.log(q)}
}
a[6]();//6
可以将for循环理解为两个块级作用域:
var a=[];
let i=0;
if(i<10){
let q = 0;
a[0]=function(){console.log(q)}
};
let i=1;
if(i<10){
let q = 1;
a[1]=function(){console.log(q)}
};
...
let i=9;
if(i<10){
let q = 9;
a[9]=function(){console.log(q)}
};
let i=10;
a[6]();
体会以下代码:
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
输出三次abc
可以看出for循环的变量i和循环体中的i在不同作用域中。
(2)使用闭包
闭包特性:
①函数嵌套函数
②内部函数可以访问外部函数的变量
③被访问的参数和变量不会被js垃圾回收机制回收
var a=[];
for (var i = 0; i < 10; i++) {
(function (n) {
let q=n;
a[n]=function(){console.log(q)}
})(i);
}
a[6]();
注:例题1:
function fc(){
let n=1;
function sum(){//函数声明时没有开辟内存空间
console.log(++n);
}
sum();//函数执行时,开辟内存空间压栈
}
fc();//2,开辟内存空间,压栈;运行完,出栈,内存被回收
fc();//2,开辟新的内存空间,压栈,与上面开辟的内存空间是独立的,互不干涉,因此打印的都是2.
例题2:
function fc(){
let n=1;
return function sum(){//返回函数的内存地址
console.log(++n);
}
}
let a=fc();//引用函数的内存地址,因此函数fc执行完不会被销毁,会继续使用。
a();//2
a();//3
let b=fc();//重新创建新的内存空间
b();//2
b();//3
区别:
function fc(){
let n=1;
return n;//此处只是返回n的值,
}
let a=fc();//变量a只是得到n的值,因此函数fc执行后其内容会被销毁。
例题3:
function fc(){
let n=1;
return function sum(){
let m=1;
function show(){
console.log(++m);
}
show();
}
}
let a=fc();
a();//2
a();//2
这个例题不是很理解啊!!!!
函数sum被引用,在外部多次执行sum时,
show函数会被多次创建新的内存空间,而不是使用原内存空间进行累加,
为啥呀???
区别以下代码:
function fc(){
let n=1;
return function sum(){//函数声明时没有开辟内存空间
let m=1;
return function show(){
console.log(++m);
}
}
//sum();//函数执行时,开辟内存空间压栈
}
let a=fc()();//此处是将show函数返回到外部
a();//2
a();//3
例题4:
var name='The window';
var obj={
name:'MY OBJ',
getNameFunc:function(){
return this.name;
}
};
alert(obj.getNameFunc());//MY OBJ
区别以下代码:
var name='The window';
var obj={
name:'MY OBJ',
getNameFunc:function(){
return function(){
return this.name;
}
}
};
alert(obj.getNameFunc()());//The window
//obj.getNameFunc()指向匿名函数function(){ return this.name;}