这是我参与更文挑战的第4天,活动详情查看: 更文挑战
闭包是什么?这是一个在javaScript中一个很难搞懂的问题。
ECMAScript 中给闭包的定义是:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。是不是看了这个定义更加的难以理解了。下面我们分析一下。
- 闭包是一个函数
- 闭包可以调用自身函数之外的定义变量
- 闭包存在定义该变量的作用域中
那么什么叫函数定义之外的变量呢?下面我们先来看看函数变量的作用域是怎么回事。
变量作用域
变量可分为全局变量和局部变量。全局变量的作用域就是全局性的,在 js 的任何地方都可以使用全局变量。在函数中使用 var 关键字声明变量,这时的变量即是局部变量,它的作用域只在声明该变量的函数内,在函数外面是访问不到该变量的。
var func = function(){
var a = 'dddd';
console.log(a); // dddd
}
func();
console.log(a); // Uncaught ReferenceError: a is not defined
来看看跟闭包关系比较大的变量生存周期。
变量生存周期
全局变量,生命周期是永久的。局部变量,当定义该变量的函数调用结束时,该变量就会被垃圾回收机制回收而销毁。再次调用该函数时又会重新定义了一个新变量。
var func = function(){
var a = 'ddd';
console.log(a);
}
func();
a就是局部变量,当函数func调用完之后a就会被销毁。
var func = function(){
var a = 'ddd';
var func1 = function(){
a += ' a';
console.log(a);
}
return func1;
}
var func2 = func();
func2(); // ddd a
func2(); // ddd a a
func2(); // ddd a a a
可以看出,在第一次调用完 func2 之后,func 中的变量 a 变成 'ddd a',而没有被销毁。因为此时 func1 形成了一个闭包,导致了 a 的生命周期延续了。
这下子闭包就比较明朗了。
- 闭包是一个函数,比如上面的 func1 函数
- 闭包使用其他函数定义的变量,使其不被销毁。比如上面 func1 调用了变量 a
- 闭包存在定义该变量的作用域中,变量 a 存在 func 的作用域中,那么 func1 也必然存在这个作用域中。 现在可以说,满足这三个条件的就是闭包了。