闭包及函数柯里化

45 阅读2分钟
1. 闭包

比较官方的解释是:闭包可以让你在一个内层函数访问到其外层函数的作用域

也就是说函数内部访问其外部的变量, 就形成了闭包

所以形成闭包需要在函数内部定义函数,当且内部函数访问外层函数的作用域变量时就形成了闭包

function fn() {
  var b = new Array(200000).fill('Green');
  function inner() {
    let innerB = b; // 内部函数 访问 外层函数变量b,形成闭包
  }
  // inner(); // 在这里调用内部函数,可以发现闭包随着函数结束,而消失
  return inner; // 向外部返回内层函数
}
var closureB = fn(); //此时将fn()赋值给全局变量closureB,此时b不会因为fn执行结束而被销毁,而是会一直存在在内存中

closureB = null; // 若使用完毕,需要像这里一样,手动释放closureB的内存

总结: 闭包的应用: 1避免全局污染, 2做一个实例来使用

最终返回出来的函数,引用外部变量的这个闭包

使用完毕时可以置为null来释放变量和闭包的空间

2.函数柯里化(实现时使用了闭包)

先上比较官方的解释: 柯里化(Currying): 是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.

再看两个概念:

1)闭包:闭包可以让你在一个内层函数访问到其外层函数的作用域

2)高阶函数:一个函数 return 一个函数

函数柯里化实现:

arguments:是一个对应于传递给函数的参数的类数组对象,通俗的说就是一个存放函数参数的类数组,像数组一样的格式,但是除了 length 属性和索引元素之外没有任何Array属性

  1. 使用使用Array.prototype.slice.call(arguments)给arguments实现数组方法的调用
  2. 实现一个可以求所传参数和的柯里化函数来举例说明函数柯里化的原理
function calc() {
  // 缓存参数
  var slice = Array.prototype.slice;
  // 缓存所有参数的总数组
  var args = slice.call(arguments);
  // 这里使用闭包
  function inner() {
    // calc(参数) =>  结果再调用的(参数)
    let innerArgs = slice.call(arguments);
    // 拼接两个数组
    args = args.concat(innerArgs); // 这里调用外层args,形成闭包
    return inner;
  }
  
  // 给inner加个方法(这里的部分是为了实现函数的功能,不是闭包的部分)
  inner.calcCount = function () {
      //给inner增加实现求和功能的函数
    return args.reduce(function (sum, n) {
      return sum + n;
    }, 0);
  }
  // 高阶函数
  return inner;// 这里calc return 了inner,形成了高阶函数
}
//这里调用一下,验证函数柯里化的实现
var xh = calc(100);
var xhtotal = xh(100)(100,100)
console.log(xhtotal.calcCount()) // 400 即4个100的和