闭包(closure)
1.1 js中变量的作用域
js中变量分为 全局变量 和 局部变量;
- 全局变量:属于window元素
- 局部变量:属于定义它的函数
全局变量在函数外部和函数内部都可以被访问到;
局部变量:仅可以在函数内部访问;
var x = "Hello World!";
function myFunction(){
var y = 12; // 定义局部变量y
console.log(y);
console.log(x); // 访问全局变量
}
有没有能够使得我们能够在外部访问函数内的局部变量;
类似于Java中我们通过 public 的getter/stter 方法,访问对象的私有属性;
闭包
1.2 嵌套函数
在js中允许定义嵌套函数
function myFunction(){
var name = "Hello World! ";
function subFunction(){
console.log(name);
}
}
在js中子函数,可以访问父函数的局部变量;
我们可否通过子函数这一跳梁,实现从外部访问函数内部的变量呢?
1.3 闭包
通过1.2 节中的子函数subFunction,就可以将闭包理解为: 定义一个函数的子函数。
闭包的作用主要有两个:
- 提供了从外部访问函数内部的局部变量
- 使得局部变量能保存在内存中
/*js内嵌函数
在js中,所有函数都能访问它们上一级的作用域。
js支持嵌套函数。嵌套函数可以访问上一层的函数变量。
*/
function add() {
var counter = 0;
function plus() { counter += 1;}
plus();
return counter;
}
document.getElementById("demo1").innerHTML = add();
function f1() {
var n = 99;
function f2() {
alert("n: " + n);
}
return f2;
}
var result = f1();
result(); // 通过子函数访问父函数的局部变量
/*
js闭包
闭包:能够读取其他函数内部变量的函数
由于js语言中,只有函数内部的子函数才能读取局部变量,
因此可以把闭包简单理解成“定义一个函数内部的函数”;
闭包本质上,就是将函数内部和函数外部连接起来的一座桥梁
*/
/*
4) 闭包的用途:
1、从外部读取函数内部的变量
2、让这些变量的值始终保持在内存中
*/
/*
5)使用闭包的注意事项:
1、闭包会使得局部变量保存在内存中,使得内存消耗过大;解决办法是,在退出函数之前,将不适用的局部变量都删除
2、闭包函数在父函数外部,改变父函数内部变量的值。注意不要随便改变父函数内部的值。
*/
function f3() {
var n = 999;
nAdd = function() { n += 1; }; // nAdd是一个全局变量,而不是局部变量;nAdd的值是一个匿名函数,匿名函数本身是一个闭包,
// 所以nAdd 相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作
function f4() {
alert(n);
}
return f4;
}
var res = f3(); // res 实际上就是闭包f4函数。函数f3中的局部变量n一致保存在内存中。
/* 原因在于:f3是f4的父函数,而f4被赋给了一个全部变量res,这导致了f4一致存在于内存中
而f4的存在依赖于f1,因此f1也始终存在于内存中,不会在调用结束后,被GC回收。
*/
res();
nAdd();
res();