关于闭包
什么是闭包?
闭包:
一个函数和词法环境的引用捆绑在一起,这样的组合就是闭包
就是一个函数A,return其内部的函数B,被return出去的函数B能够在外部访问A函数内部的变量(定义在函数内部的函数)
这时候就形成了一个函数B的变量背包,A函数执行结束之后这个变量背包也不会被销毁
并且这个变量背包在A函数外部只能通过B函数来访问(闭包就是一座将函数内部和外部连接起来的桥梁)
原理:
作用域链,当前作用域链可以访问上级作用域中的变量
闭包解决的问题:
能够让函数作用域中的变量在函数执行结束之后不被销毁,同时也能在函数外部可以访问函数内部的局部变量。
闭包带来的问题:
由于垃圾回收机制不会将闭包中的变量销毁,内存消耗会很大,所以不能滥用闭包,否则会造成网页性能问题,
也可能导致内存泄露,内存泄露积累多了就容易导致内存溢出(解决办法是在退出函数之前,将不使用的局部变量全部删除)
闭包的主要作用:
模仿块级作用域:
已知数组var arr = ['a','b','c','d','e','f'],每过1秒打印一下数组中的值:
未有块级作用域时:setTimeout属于异步任务,for循环结束后,每秒输出的都为 'e'
var arr = ["a", "b", "c", "d", "e"]; for (var i = 0; i < arr.length; i++) { var item = arr[i]; setTimeout(function() { console.log(item); }, 1000 * (i + 1)); }
ES5:借助IIFE(弥补JS在scope方面的缺陷)
var arr = ["a", "b", "c", "d", "e"]; for (var i = 0; i < arr.length; i++) { (function(j){ var item = arr[j]; setTimeout(function() { console.log(item); }, 1000 * (j + 1)); })(i); }
ES6:let、const块级作用域
var arr = ["a", "b", "c", "d", "e"]; for (let i = 0; i < arr.length; i++) { const item = arr[i]; setTimeout(function() { console.log(item); }, 1000 * (i + 1)); }
实现柯里化:
柯里化是一种转换,将 f(a,b,c) 转换为可以被以 f(a)(b)(c) 的形式进行调用。
在构造函数中定义特权方法:
有权访问私有变量、私有函数的公有方法就是特权方法
Vue中数据响应式Observe中使用闭包等:
function defineRealive(target, key, value){ return Object.defineProperty(target, key, { get(){ console.log(`通过getter获取数据:${value}`); return value; }, set(val){ console.log(`通过setter设置数据:新值-${val};旧值-${value}`); // 形参也是一个普通的局部变量,只是可能我们平时使用的时候,一般不会对形参进行赋值操作,因为大部分情况,形参都是外部传入的数据,我们无需修改。 // 这里就用到了闭包的原理,value是外层函数defineRealive的参数,而我们实际上使用value确是在内层的get或set方法里面 // 这样就形成了一个闭包的结构了。根据闭包的特性,内层函数可以引用外层函数的变量,并且当内层保持引用关系时外层函数的这个变量 // 不会被垃圾回收机制回收。那么,我们在设置值的时候,把val保存在value变量当中,然后get的时候再通过value去获取,这样,我们再访问 // obj.name,无论是设置值还是获取值,实际上都是对value这个形参进行操作的。 value = val; } }); } let obj = { name: 'kiner', age: 20 }; Object.keys(obj).forEach(key=>defineRealive(obj, key, obj[key])); obj.name = 'kanger'; obj.age = 18; // 控制台输出:kanger 18 console.log(obj.name,obj.age);
内存泄露与内存溢出:
内存泄露是指程序中已动态分配的堆内存由于某种原因,程序未释放或无法释放,造成的内存浪费
导致程序运行速度减慢甚至系统崩溃等严重后果(即不再会被使用的对象的内存不能被回收)
内存泄后堆积的结果就是内存溢出
参考: