JavaScript的闭包函数无论在面试还是写业务时,我们都经常碰到,我们今天来讲一下闭包
闭包
我们平时在面试被问到什么叫做闭包时,大多数人回答的是闭包就是能够读取其他函数内部变量的函数,其实更为准确的回答是一个记住当前执行环境且不被销毁的函数就是闭包,闭包形成的原理就是外部作用域被内部函数引用就形成了闭包。
闭包的定义
函数能够"记忆住"其定义所处的环境,即使函数不在其定义的环境中被调用,也能访问定义时所处环境的变量;
闭包函数
// 当一个函数执行时,形成了不被销毁的作用域就是闭包,闭包是函数本身和该函数声明所处环境的组合. function fun() { // 局部变量 var name = '前端若水'; // 定义闭包函数 function fic() { alert(name) } //把闭包函数返回出去,不调用 return fic; }; // 把闭包函数赋值出去 var c = fun(); // 调用闭包函数 c();
闭包函数的特性
闭包函数作为常用的功能,肯定有着一些让我们为之着迷的点,所以我们才会去使用,它具有以下优点
- 记忆性:当闭包产生时,函数所处环境的状态会始终保持在内存中,不会在外层函数调用后被自动清除
- 模拟私有变量:java 和C++等语言中,有私有属性的概念,但是js中只能通过闭包进行模拟
闭包函数的记忆性
// 闭包记忆性:当前有AB俩个小区,a小区体温达标是低于37.1,b小区是37.8,用闭包实现 /** * @param {Number} temperature 最大温度 * @return {function} 闭包函数 */ function Ctmp(temperature) { //传递最大温度必须为数字 if (typeof temperature != 'number') console.error('当前传递体温有误'); //闭包函数,传递一个当前温度,用于和最大温度进行判断 function tem(n) { //再次进行判断最大温度为数字,防止出现错误 if (typeof temperature != 'number') console.error('当前传递体温有误'); //判断当前温度是否小于最大温度,小于达标,大于则太高 if (n < temperature) { console.log('体温达标', n); } else { console.log('体温太高', n); } } return tem; }; // a var Fn_a = Ctmp(37.1); Fn_a(37.2); // b var Fn_b = Ctmp(37.8); Fn_b(37.6);
闭包函数模拟私有变量
/* 模拟私有变量 */ // 定义一个变量,保证这个变量只能进行指定操作,而不能进行其他操作 function fn1() { // 私有变量 var a = 0; //闭包函数 function action() { return a; } return action; } var fnKey = fn1(); 复制代码
闭包函数实现一个小功能
通过上述我们了解了闭包函数的特性,我们现在就把闭包函数的记忆性和模拟私有变量一块用起来实现一个小功能吧,我们声明一个函数,里面有个变量,我们通过执行闭包函数,可以获得一个对象,对象里面由于用到了外部作用域的变量所以不会被销毁,也可以进行对变量进行操作,对其修改和读取
function fn2() { // 私有变量 var a = 1; // 返回一个对象,对象里面是操作私有变量的方法 return { //获取方法 get: function() { return a; }, //自增方法 add() { a++; }, //幂次方方法 pow() { a *= a; } } } // 接受返回的对象进行使用 var obj = fn2(); //对当前闭包函数中的私有变量进行自增 obj.add(); //获取私有变量 console.log(obj.get());
闭包注意点
闭包虽好但是不能滥用,否则会造成网页的性能问题(网页卡顿),严重时可能导致内存泄漏,内存泄漏是指程序中已动态分配的内存由于某种原因未释放或无法释放
坚持努力,无惧未来!