◆
JavaScript 闭包详解:原理、作用与产生条件
什么是闭包
- 有权访问另一个函数作用域的变量的函数
- 简单的说,
Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。 - 闭包是嵌套的内部函数
- 闭包存在于嵌套的内部函数中
闭包的主要作用
- 可以读取函数内部的变量
- 让这些变量的值始终保持在内存中,变量或参数不会被垃圾回收机制回收 GC
产生闭包的条件
- 函数嵌套
- 内部函数引用了外部函数的数据(变量/函数)
闭包的优、缺点
优点
- 变量长期驻扎在内存中
- 避免全局变量的污染
缺点
- 常驻内存会增大内存的使用量
- 使用不当会造成内存泄露
- 闭包会在父函数外部,改变父函数内部变量的值
闭包使用详解
当想要的得到 f1 函数的局部变量时,正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数
function f1() {
var n = 999;
function f2() {
console.log(n); // 999
}
}
上面代码中,函数 f2 就在函数 f1 内部,这时 f1 内部的所有局部变量,对 f2 都是可见的。但是反过来就不行,f2 内部的局部变量,对 f1 就是不可见的。 这就是 JavaScript 语言特有的”链式作用域”结构,子对象会一级一级地向上寻找所有父对象的变量。 所以,父对象的所有变量,对子对象都是可见的,反之则不成立。既然 f2 可以读取 f1 的局部变量,那么只要把 f2 作为返回值,我们不就可以在 f1 外部读取它的内部变量了吗!
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 999
上面代码中,函数 f1 的返回值就是函数 f2,由于 f2 可以读取 f1 的内部变量,所以就可以在外部获得 f1 的内部变量了。闭包就是函数 f2,即能够读取其他函数内部变量的函数。 由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
- 闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中 请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果。
function fxs(fx) {
return function () {
return fx++;
};
}
var inc = fxs(5);
inc(); // 5
inc(); // 6
inc(); // 7
上面代码中,fx 是函数 fxs 的内部变量。通过闭包,fx 的状态被保留了,每一次调用都是在上一次调用的基础上进行计算。从中可以看到,闭包 inc 使得函数 fxs 的内部环境,一直存在。所以,闭包可以看作是函数内部作用域的一个接口。为什么会这样呢?原因就在于 inc 始终在内存中,而 inc 的存在依赖于 fxs,因此也始终在内存中,不会在调用结束后,被垃圾回收机制回收。

还没有留言,来发表第一条吧~