Javascript中的闭包是什么?它有哪些特点?有什么应用场景?

闭包(Closure)是 JavaScript 中的一个重要概念。它指的是:一个函数和对其周围状态(scope)的引用捆绑在一起的实体。
简单来说,闭包让函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行的。

闭包有以下主要特点:

  1. 可以读取函数内部的变量
  2. 读取的时候,会使用其时的变量值
  3. 函数的作用域链包含着这个闭包创建时的作用域

例如:

function makeCounter() {
  let count = 0;

  return function() {
    count++;
    return count; 
  }
}

let counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2

这里 counter 是闭包,它包含了对包含它的 makeCounter 函数作用域的引用。所以每次调用 counter 都可以修改和访问 makeCounter 内的 count 变量。

闭包的主要应用场景有:

  1. 封装变量
  2. 函数柯里化
  3. 装饰器模式
  4. 细粒度权限控制
  5. 模拟私有方法

例如:

// 封装变量
function makeCounter() {
  let count = 0;
  return {
    increase() {
      count++;
    },
    getCount() {
      return count;
    }
  };
}

let counter = makeCounter();
counter.increase(); 
counter.getCount(); // 1

// 函数柯里化
function curry(fn) {
  return function(a) {
    return function(b) {
      return fn(a, b);
    } 
  };
}

let addCurry = curry((a, b) => a + b); 
let add10 = addCurry(10);
add10(20); // 30

// 装饰器模式
function makeColor(color) {
  return function(target) {
    target.color = color;
  }
}

@makeColor('red') 
class Button {
  constructor() {
    console.log(this.color); 
  }
}

let button = new Button(); // red

所以总结来说,闭包是 JavaScript 语言极为重要的功能,它使得 JavaScript 的函数更加强大与灵活。
理解闭包的工作机制与应用场景,可以帮助我们编写更加优雅与强大的代码。
在工作中,我们应熟练运用闭包来封装数据,实现柯里化,装饰器等功能。