闭包
1、定义:
嵌套在函数作用域中的函数,称为闭包函数。该作用域称为闭包环境。通过闭包函数可以访问闭包函数所在函数作用域中的形参与变量
2、表现形式:
使函数外部能够调用函数内部定义的变量
3、工作原理:
利用了js中的垃圾回收机制,当一个函数被调用时,开辟空间,函数调用结束,释放空间,垃圾回收机制释放被调用结束的函数时,发现函数的变量正在被其他的函数调用,这些变量不会被释放,而且被永久驻留在内存,只有退出程序,才会被释放,或者是手工释放(=null)
4、变量的作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域分类:全局变量和局部变量。
特点:
1、函数内部可以读取函数外部的全局变量;在函数外部无法读取函数内的局部变量。
2、函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
5、使用闭包的注意点
1)滥用闭包,会造成内存泄漏:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除,==null销毁闭包。
2)会改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public
Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
函数柯里化
实现 sum(1)(2)(3) 返回结果是1,2,3之和
1.函数柯里化(curry)是函数式编程里面的概念。是指每次调用函数时,它先接受一部分参数,并返回一个函数,然后再传递剩下的一部分参数,返回一个函数,直到传递所有参数为止 。
2. carry是用来生成 fn 函数成为柯理化函数的工具函数,add1 是让其成为柯理化函数的目标函数(也就是 fn) 根据传入的参数个数
3.(args.length) 是否大于等于原函数所需参数个(fn.length)如果是,则执行当前函数;否则返回一个函数(carry函数)
// carry是用来生成 fn 函数成为柯理化函数的函数,
function carry(fn, ...args) {
//传入的参数个数 (args.length) 是否大于等于原函数所需参数个数 (fn.length) ,如果是,则执行当前函数;否则返回一个函数
if (args.length >= fn.length) {
return fn(...args);
} else {
return function (..._args) {
return carry(fn, ..._args, ...args)
};
}
}
function add1(x, y, z) {
return x + y + z;
}
let add = carry(add1);
console.log(add(1, 2, 3));
console.log(add(1, 2)(3));
console.log(add(1)(2, 3));
主要有三个作用: 参数复用、提前返回和 延迟执行
比如,我们有一个柯理化函数 add(最多传入3个参数),那么 add(1, 2)(m) 的结果就是 1+2+m,我们只需要这样做:
令 fn_1_2 = add(1, 2) ,之后 fn_1_2(m) 就只需直接传入一个值 m,不需要传入 1和2,达到复用 1和2 这两个参数了
let fn_1_2 = add(1)(2);
console.log(fn_1_2(3)) // 6
console.log(fn_1_2(4)) // 7
就是参数复用,而 提前返回 和 延迟执行 也很好理解,因为每次调用函数时,它只接受一部分参数,并返回一个函数(提前返回),直到(延迟执行)传递所有参数为止。