闭包
- 闭包是在局部作用域的前提下,一个函数return一个复杂数据类型,这个复杂数据类型就是闭包空间,可以通过闭包在整个函数外访问到函数内的局部变量
垃圾回收机制(GC)
- 当一个对象在使用后不需要再用到,就会被垃圾回收机制清除掉释放内存
获取闭包中的变量
- 在函数调完之后,后面还存在会用到函数里面的东西的时候,这整个函数会被保留下来
有个变量接收了fn()的返回值,而且返回值是个复杂类型,这个a一直指向着这个复杂数据类型的返回值,这个fn就不会被删除
通过这个概念,可以访问到闭包内的变量
function fn(){
let a = 10;
return function(){
a++;
console.log(a);
}
}
let b = fn();
b();
b=null;//把b重新赋值成一个别的值,b不再需要fn()的内容,这个fn()也就不存在堆内存中了
可以看到,b()通过fn()的返回值获取到了fn()里面的a并对其进行操作
柯里化
- 简化调用函数的写法,把多个形参的函数变成一个形参的函数,你传入的实参多于初始的那个形参,但你想处理所有的实参,通过柯里化,他会把传进的实参先保留下来,再把后面的实参拿过来和保留的实参一起使用。
function fn(num1,num2){
return num1+num2;
}
console.log(fn(2,2));
上面这个代码可以写为
function fn(num1){
return function(num2){
return num1+num2;
}
}
console.log(fn(2)(2))
这样就可以把多个形参的函数写成一个形参,再利用箭头函数简化可以写成
let fn =num1=>num2=>num1+num2;
console.log(fn(2)(2))
利用这个概念实现自动柯里化
function klh(fn){
return function sum(...num1){
if(fn.length<=num1.length){
return fn.call(null,...num1);
}else{
return function(...num2){
return sum.apply(null,[...num1,...num2])
}
}
}
}
function num(a,b,c,d){ //用于处理参数做什么事的函数
return a+b+c+d;
}
let s = klh(num);
console.log(s(1,2)(3)(4));
//简单理一下逻辑,从后面开始看,s的初始是klh的返回值sum函数
//s(1,2)也就是sum(1 2),他的长度小于num里形参的长度(个数),然后返回function(...num2)函数,记住这是num1是1,2
//这时s(1,2)是上一不返回的函数整体,s(1,2)(3)也就成了funtion(...num2)返回到sum函数,参数是[...num1,...num2]也就是[1,2,3]
//s(1,2)(3)就成了sum(1 2 3),他的长度依旧小于num的长度,这是num1成了[1,2,3],
//可以看出,过程就是把参数保留下来并进行拼接起来
//重复以上步骤,直到num1的长度num1成了[1,2,3,4]的时候长度等于num的长度,
//返回fn.call(null,...num1),也就是num(...num1),也就是num(1,2,3,4),然后返回num函数里面的返回值。
箭头函数简化后
function num(a,b,c,d){
return a+b+c+d;
}
let klh = fn => sum=(...num1)=>fn.length<=num1.length?fn.call(null,...num1):(...num2)=>sum.apply(null,[...num1,...num2])
let s = klh(num);
console.log(s(1)(2)(3)(4));
当需要对参数做不同的计算的时候,只需要改num函数就行
- 这样做的好处是什么呢,比如公司考勤,你每天的工作时长就是一个实参,你肯定不想每天都去计算前几天一共干了多少小时,而是先把他记录下来,在要发工资的时候再去计算,这就是柯里化的逻辑。