闭包
在计算机科学中,闭包,又称词法闭包或函数闭包,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。(引自维基百科)
简单来说,闭包就是函数内嵌套函数,指有权访问另一个函数作用域的变量的函数,是一种特殊的对象。
闭包解决的是函数外部调用函数内部的数据的问题。
function fn() {
var a = 1;
return function () {
return ++a;
}
var f = fn();
console.log(f());
console.log(f());
// 变量使用完后忘记销毁,这种变量多了就会造成内存泄漏
// 简单解决内存泄漏
f = null;
}
内存溢出:指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory
内存泄漏:指程序申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可忽略,但内存泄漏堆积后果很严重 memory leak
内存泄漏多了就会造成内存溢出 => memory leak会最终会导致out of memory
优点
- 可以读取函数内部的变量
- 可以让这些变量的值始终保存在内存中
缺点
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,可能导致内存泄露。
- 闭包会在父函数外部,改变父函数内部变量的值。
柯里化
英语:Currying(果然是满满的英译中的既视感),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术 ————维基百科
// 普通的add函数
function add(x, y) {
return x + y;
}
// Currying后
function curryingAdd(x) {
return function (y) {
return x + y;
}
}
add(1, 2) // 3
curryingAdd(1)(2) // 3
优点
- 复用参数 : 需要输入多个参数,最终只需输入一个,其余通过arguments来获取
function curryingCheck(reg){
return function (txt) {
return reg.test(txt);
}
};
var hasNumber = curryingCheck(/\d+/g);
var hasLetter = curryingCheck(/[a-zA-Z]+/g);
hasNumber('test1')
hasNumber('test')
hasLetter('123')
-
提前返回 : 避免重复去判断某一条件是否符合,不符合则return 不再继续执行下面的操作
-
延迟执行 : 避免重复的去执行程序,等真正需要结果的时候再执行
面试题: 实现一个add方法,使计算结果满足如下预期: add(1)(2)(3) = 6; add(1, 2, 3)(4) = 10; add(1)(2)(3)(4)(5) = 15;
function add() {
// 第一次执行时,定义一个数组专门用来存储所有参数
var _args = Array.prototype.slice.call(arguments);
// console.log(_args);
// 在内部声明一个函数,利用闭包的特性保存_args并手机所有的参数
var _adder = function () {
_args.push(...arguments);
return _adder;
}
// 利用toString()隐式转换,当最后执行时隐式转换,并计算最终的返回值
_adder.toString = function () {
return _args.reduce(function (prev,item) {
return prev + item;
})
}
return _adder;
}