JavaScript 闭包问题
01 闭包的定义
当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。
02 闭包的作用
- 实现公有变量(eg.函数累加器)
- 可以做缓存(存储结构)
- 可以实现封装,属性私有化
- 模块化开发,防止污染全局变量
03 闭包解决方法
下面的代码存在闭包问题,本意是在test函数中,给arr数组的每一个元素循环赋值为一个能够打印索引的匿名函数,并用myarr变量来接收test函数的返回值arr数组,接着用循环对myarr中每个元素执行,并打印对应的索引。但最后的打印结果是10个10。
function test() {
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function() {
document.write(i + " ");
}
}
return arr;
}
var myarr = test();
for (var j = 0; j < 10; j++) {
myarr[j]();
}
// 输出--> 10 10 10 10 10 10 10 10 10 10
运行截图:
解决方法1:采用立即执行函数(推荐)
function test() {
var arr = [];
for (var i = 0; i < 10; i++) {
(function(j) {
// j = 0 1 2 3 4 5 6 7 8 9
arr[j] = function() {
document.write(j + " ");
}
}(i));
}
return arr;
}
var myarr = test();
for (var j = 0; j < 10; j++) {
myarr[j]();
}
运行截图:
解决方法2:用let定义变量i
function test() {
var arr = [];
for (let i = 0; i < 10; i++) {
arr[i] = function() {
document.write(i + " ");
}
}
return arr;
}
var myarr = test();
for (var j = 0; j < 10; j++) {
myarr[j]();
}
运行截图:
04 闭包例题练习
例题1:考查闭包输出
// 例题1
var a = 0,
b = 0;
function A(a) {
A = function(b) {
console.log("inside:");
console.log(a + b++); //4
}
console.log("outside:");
console.log(a++); //1
}
A(1);
A(2);
运行截图:
代码解析:在第一次调用A函数的时候, A函数被重新赋值为了function(b){console.log("inside:");console.log(a + b++);};
在console.log
输出a
之后,a的值加1,即a=2
。此时需要注意,在初始的A当中,形参a其实是一个局部变量,当重置A函数的时候,新的A函数调用了原有A函数作用域中的局部变量a,构成了闭包,a这个局部变量被保存(所以此时a=2
,新的形参b=2
,相加得4)。
例题2:私有化变量
// 例题2:私有化变量
function Person(name, age, sex) {
var a = 0;
this.name = name;
this.age = age;
this.sex = sex;
function sss() {
a++;
document.write(a);
}
this.say = sss; //将sss这个函数赋给了say变量
//相当于
//this.say = function() {
// a++;
// document.write(a);
//};
}
var oPerson = new Person();
oPerson.say(); //1
oPerson.say(); //2
var oPerson1 = new Person();
oPerson1.say(); //1
运行截图:
个人笔记,欢迎大家交流探讨!