JavaScript 闭包&基于闭包实现柯里化curry和bind
闭包:
- 1 函数内声明了一个函数,并且将这个函数内部的函数返回到全局
- 2 将这个返回到全局的函数内中的函数存储到全局变量中
- 3 内部的函数调用了外部函数中的局部变量
闭包简述:
- 有权访问另一个函数局部作用域中的变量的函数
闭包清除:
- 将存储该内部函数的全局变量赋值为null,此时内部函数没有被引用,被垃圾回收机制回收
- 由此也可以得出,闭包形成的原因------ 基于引用计数与标记清除的JavaScript垃圾回收机制
优点:
- 有私有变量存在
- 避免全局污染
- 防止私有变量被垃圾回收
缺点:
- 势必造成内存泄漏
示例:
function fn1() {
var a = 1;
function fn2(){
var b = 0;
a ++;
b++;
console.log(a,b);
}
return fn2;
}
var fns = fn1();
fns();
fns();//3,1
//第二次执行fns,fns又创建新的执行期上下文,此间b经历了残忍地再初始化和重建
//而a因为在fn2的局外,又为全局变量fns所庇佑,于是得以苟且偷生,并继续接下来的运算
function fn1(s){ var a = 1; var o = {a:1}; return function(){ a++; o.a++; console.log(a,o.a); } } var fn = fn1(); fn(); fn(); fn(); fn();//5,5 fn = null;//清除闭包
运用:
- curring
- bind
curring :
1 函数多行执行
/** 闭包实现柯里化 柯里化主要做两件事情: 1 执行函数参数个数不为0时, 将参数列表用concat连接存储在数组arr中 2 否则执行参数列表为arr的执行函数 步骤: 1 在外部函数新建一个数组arr 2 当参数个数不为0时, arr在内部函数存储每次函数执行的参数列表, 返回并用全局变量接收内部函数, 形成闭包 3 当前执行函数的参数个数不为0时, 将参数列表存进数组 4 当执行函数的参数个数为0时, 执行参数列表为arr的执行函数 */ const add = (...args) => args.reduce((a, b) => a + b) const curry = function (fn) { const args = [] function temp(...newArgs) { if (newArgs.length) { args.push(...newArgs) return temp } return fn.apply(this, args) } temp.toString = function () { // console.log(add.apply(null, args)); return add.apply(null, args); } return temp } console.log(curry(add)(1)(2, 3)()); console.log('%s', curry(add)(2)(2, 3));
bind:
/* 实现bind: 将函数中的this指向绑定到bind函数的参数中 用apply实现 */ function bind(fn, obj) { return function () { //这里的传参要看是谁调用 console.log(arguments);//3,5,这里的参数是setTimeout传进来的 fn.apply(obj, arguments); } } function abc(_a, _b) { this.a = _a; this.b = _b; } var obj = {}; setTimeout(bind(abc, obj), 200, 3, 5);//执行function(){abc(3,5)}