javascript的闭包与变量域

发布时间:2019-10-21编辑:脚本学堂
本文介绍下,有关javascript中闭包与变量域的例子,有需要的朋友参考下。

javascrpt闭包、变量域的例子:
 

复制代码 代码示例:
for(var i=0;i<10;i++) {
setTimeout(function() {
console.log(i);
}, 300);
}
 

运行结果:连续输出了10个10。
因为 “i” 这个变量在内存里只保存了一份。
当调用settimeout方法时,往js事件线程的等待队列排入了十个执行函数,一直到每个300ms结束,这十个执行 函数才被调用,此时内存里的 “i” 这个变量经过十次循环最终值已变成了10 。所以就输出了10个10了。

如何输出0-9呢?
可以用闭包把代码改造下:
 

复制代码 代码示例:
for(var i=0;i<10;i++) {
setTimeout((function(j) {
return function() {
console.log(j);
}
})(i), 300);
}
 

此时就会输出正确的结果了,为什么?因为在给settimeout传参前,先使用闭包重新生成了一个执行函数,并且把当时循环里的"i"的值作为参 数传入到闭包函数中,结果函数无论什么时候执行,都打出的是当时被传入的那个值。

说明:在给函数传参时,如果传入的参数是位于栈内存上的时候,会将栈 内存值复制一份传入到函数中。
那如果所传参数是个对象,也就是存在于堆内存上时会怎么办。

接着做一个实验,这次的循环对象是一个对象字面量:
 

复制代码 代码示例:
var obj = {j:0};
for(var i=0;i<10;i++) {
obj.j++; // www.jb200.com
setTimeout((function(o) {
return function() {
console.log(o.j);
}
})(obj), 300);
}
 

输出了什么?还是10个10!为什么?虽然还是使用闭包将当前循环的对象状态作为参数传入执行函数中,但传入的只是栈内存上的变量指针,位于堆内存上的内存仍然只有一份,所以这10个等待任务最终开始执行时,输出的都是同一份内存值。

结论:
1、对于基础数据类型,函数传参的时候会将变量值复制一份传入到函数中。
2、对于对象数据类型,函数传参时是将变量的指针复制一份,真正的变量值只有一份。
由于变量指针和基础类型变量都位于栈内存上,所以传参就是将栈内存复制一遍,堆内存不变。