持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 9 天,点击查看活动详情
闭包的概念
指有权访问另一个函数作用域中的变量的函数,一般情况就是在一个函数中包含另一 个函数。
闭包的作用
访问函数内部变量、保持函数在环境中一直存在,不会被垃圾回收机制处理; 简单地说:就是在函数的局部范围内声明一个封闭的环境,此环境不会被垃圾回收探测到。保证了数据 的安全唯一性
想了解闭包,首先要了解什么是全局变量,什么是局部变量
局部变量
a 是一个局部变量。局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。
函数可以访问由函数内部定义的变量。
function sum(){
var a=4;
return a*a;
}
console.log(sum())
console.log("输出:"+a);
全局变量
a 是一个全局变量。在web页面中全局变量属于 window 对象。全局变量可应用于页面上的所有脚本。
函数也可以访问函数外部定义的变量。
b=4;
function sum(){
c=5;
var a=4;
return a+b+c;
}
console.log(sum())
console.log("输出:"+b);
console.log("输出:"+c);
console.log("输出:"+a);
-
全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
-
不适用var声明的变量,就是全局变量
-
用 var声明,并且在函数的内部。这样的变量叫做局部变量,有效范围只能在其声明的函数内部。
-
全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。
需求:设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的。
count=0;
function add(){
count++;
}
add();
add();
add();
console.log(count);
计数器数值在执行 add() 函数时发生变化。但问题来了,页面上的任何脚本都能改变计数器,即便没有调用 add() 函数。
谁都可以访问 count,所以 count 变量并不安全,因为是全局变量。
如何才能安全呢?将 count声明为局部变量.
function add(){
var count=0;
return count++;
}
add();
add();
add();
console.log(add());
本意是想输出 3, 但事与愿违,输出的都是 0 !
所有函数都能访问全局变量。实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
function add(){
var count = 0; //局部变量
function jia(){
return count++;
}
jia();
return count;
}
add();
add();
add();
console.log(add());
如果每次只调用 add()里面的 jia()就好了。ok,闭包帮你解决此问题!
自我调用
var add = (function () {
var counter = 0;
return function () {
return counter += 1;
}
})();
add();
add();
add();
console.log(add());
变量 add 指定了函数自我调用的返回字值。自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。这个叫作 JavaScript 闭包。 它使得函数拥有私有变量变成可能。计数器受匿名函数的作用域保护,只能通过 add 方法修改。
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不 受外界干扰。直观的说就是形成一个不销毁的栈环境。
- 闭包的优点: 方便调用上下文中声明的局部变量 逻辑紧密,可以在一个函数中再创建个函数,避免了传参的问题
- 闭包的缺点: 因为使用闭包,可以使函数在执行完后不被销毁,保留在内存中,如果大量使用闭包就会造 成内存泄露,内存消耗很大