12,闭包
函数作为返回值,在Java函数本质还是一个对象,因此可以把一个函数作为返回值
function f1() {
return function (x) {
return x*x;
}
}
var res = f1();//调用f1获得一个代执行的函数
res(2);//4
闭包深入理解:在局部作用域中访问了其他局部变量
//循环返回函数值,注意引用的循环变量,会发生改变!!!!
//(js的变量提升)函数在调用时候访问的是一个全局作用域的i
function f() {
var arr=[];
for (var i = 0; i < 3 ; i++) {
arr.push(function () {
return i*i;
})
}
return arr;
}
f[0]();//0
f[1]();//1
f[2]();//4
//闭包可以理解为一个闭包就是一个没有释放资源的栈区
// ,栈区内的变量处于激活状态。
// 上面的例子中for循环在执行时系统分配内存,js执行线程创建执行栈区,
// 执行时候检测到立即执行函数里的变量i被内部函数引用,所以该栈区在内存中没有被释放,
// 函数(数组元素)被调用时候根据作用链首先访问到的是上一级作用域(立即执行函数)的变量。
//解决方法1:通过构造一个立即执行的函数,数组中的每个函数有单独的作用域
//每个函数就处于一个立即执行函数的函数作用域中
function f5() {
var arr=[];
for (var i = 0; i < 3 ; i++) {
arr.push(function (i) {
//让f3函数的作用域限定在一个立即执行函数的函数作用域
return function () {
return i*i;
}
}(i));
}
return arr;
}
var result=f5();
result[0]();//0
result[1]();//1
result[2]();//4
//解决方法2:这里我发现将var改为let,就没事了.ES6标准中,通过let构建块级作用域,解决问题
function f4() {
var arr=[];
for (let i = 0; i < 3 ; i++) {
arr.push(function () {
return i*i;
})
}
return arr;
}
let f2 = f4();
f2[0]();//9
f2[1]();//9
f2[2]();//9
- 利用闭包封装一个私用变量
function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;
}
}
}
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13