1.什么是闭包
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。 ——摘自百度百科
理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象,这就是闭包的重要概念。
一个闭包的例子
function a(){
var i=0;
function b(){
alert(++i);
} return b;
}
var c = a();
c(); //弹出i的值 1- 函数b嵌套在函数a内部
- 函数a返回函数b
- 外部再调用函数b,就可以获取函数a中的局部变量
或者说闭包就是子函数可以使用父函数的局部变量,还有父函数的参数。
为什么会形成闭包
所有函数都能访问全局变量。
如何销毁闭包
释放对闭包的引用 使引用变量为空。
javascript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收机制回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。
2.作用域
在JavaScript中,作用域为可访问变量,对象,函数的集合。
javaScript局部作用域
变量在函数内部声明,只能在函数内部访问。
function demo() {
var a = 6; //局部作用域
}函数内声明需加var否则仍是全局变量。
JavaScript全局作用域
变量在函数外定义,网页中的所有脚本和函数均可使用。
var num = 1; //全局变量
//此处可调用num
function a() {
//此处可调用num
}3.作用域链
当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain,不简称sc)来保证对执行环境有权访问的变量和函数的有序访问。作用域第一个对象始终是当前执行代码所在环境的变量对象
原理
只要搞清楚JavaScript作用域链的原理我们就很容易理解作用域链。
- 函数在执行的过程中,先从自己内部寻找变量
- 如果找不到,再从创建当前函数所在的作用域去找,从此往上,也就是向上一级找。
function foo() {
let a = 1;
function bar() {
let a = 2;
function baz() {
let a = 3;
console.log(a);
}
baz();
}
bar();
}
foo(); let是块级作用域,只可在自己所在的花括号内被调用。我们先从自己内部寻找变量,console.log(a)在函数baz中,而函数baz内部变量 a = 3, 所以输出a = 3;
let a = 1;
function foo(){
let a = 2;
function baz(){
console.log(a);
}
bar(baz);
}
function bar(fn){
let a = 3;
fn();
}
foo();
我们先从自己内部寻找变量,函数baz内部并未定义任何变量,所以我们再从创建当前函数所在的作用域去找,也就是他的父级,发现定义了a = 2。