闭包:指有权访问另一个函数作用域中的变量的函数。
闭包是指这样的作用域,它包含有一个函数,这个函数可以调用被这个作用域所封闭的变量、函数或者闭包等内容。通常我们通过闭包所对应的函数来获得对闭包的访问。
函数作用域
function init() {
let name = "Mozilla";
// name 是一个被init创建的局部变量
function displayName() {
// displayName() 是一个内部函数,
alert(name);
// 一个闭包使用在父函数中声明的变量
//注意,不要误认为闭包一定是被返回的函数,只要可以调用另外一个函数作用域的变量的函数就叫做闭包。
}
displayName();
}
init();
函数 init() 创建了一个局部变量 name和一个名为 displayName() 的函数。 displayName() 是一个内部函数——定义于 init() 之内且仅在该函数体内可用。displayName() 没有任何自己的局部变量,然而它可以访问到外部函数的变量,即可以使用父函数 init() 中声明的 name 变量。
闭包
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
运行这段代码的效果和之前的 init() 示例完全一样:字符串 “Mozilla” 将被显示在一个 JavaScript 警告框中。其中的不同 — 也是有意思的地方 — 在于 displayName() 内部函数在执行前被从其外围函数中返回了。
这段代码看起来别扭却能正常运行。在一些编程语言中,函数中的局部变量仅在函数的执行期间可用。一旦 makeFunc() 执行过后,我们会很合理的认为 name 变量将不再可用。然而,因为代码运行的没问题,所以很显然在 JavaScript 中并不是这样的。
这个谜题的答案是 myFunc 变成一个 闭包 了。 闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。在我们的例子中,myFunc 是一个闭包,由 displayName 函数和闭包创建时存在的 “Mozilla” 字符串形成。
闭包的用处
1,闭包可以访问当前函数以外的变量
function getOuter(){
var date = '815';
function getDate(str){
console.log(str + date); //访问外部的date
}
return getDate('今天是:'); //"今天是:815"
}
getOuter();
getDate是一个闭包,该函数执行时,会形成一个作用域A,A中并没有定义变量date,但它能在父一级作用域中找到该变量的定义。
2、即使外部函数已经返回,闭包仍能访问外部函数定义的变量
function getOuter(){
var date = '815';
function getDate(str){
console.log(str + date); //访问外部的date
}
return getDate; //外部函数返回
}
var today = getOuter();
today('今天是:'); //"今天是:815"
today('明天不是:'); //"明天不是:815"
3、闭包可以更新外部变量的值(模拟私有方法)
function updateCount(){
var count = 0;
function getCount(val){
count = val;
console.log(count);
}
return getCount; //外部函数返回
}
var count = updateCount();
count(815); //815
count(816); //816