还有人不懂闭包?

141 阅读3分钟

什么是闭包?谈谈你的了解

JS闭包指的是一个函数能够访问并操作其外部作用域的变量,即使这个函数在外部作用域已经执行完毕,这些变量依然可以被访问和修改。

也就是延长了其生命周期

闭包的实现方式是在一个函数内部定义另一个函数,并将其作为返回值返回。这个内部函数可以访问外部函数的局部变量,而外部函数的局部变量则被保存在返回的内部函数中,形成了一个闭包。

function outerFunction() {    
  var privateMethod = function() {    
    console.log("This is a private method");    
  };  
  
  return privateMethod;    
}  
  
const privateMethod = outerFunction();    
privateMethod(); // 输出 "This is a private method"

从代码我们可以看出,闭包的一种形式就是很简单的函数里面在套一个函数,调用上层函数获取下面的函数的东西

闭包的高级操作

闭包实现高并发

function addNumbers(a, b) {    
  var result = 0;    
  function worker() {    
    result += a + b;    
  }    
  new Thread(worker).start();    
  return result;    
}  
  
// 在函数内部创建一个新的闭包,用于存储线程对象    
var thread = null;  
  
// 在函数外部创建一个新的线程,并使用闭包创建一个新的线程对象    
addNumbers(11);  
  
// 在函数外部使用闭包访问线程对象    
if (thread) {    
  thread.join();    
}  
console.log(result); // 输出 2

在这个例子中,addNumbers 函数返回了一个闭包,该闭包在内部创建了一个新线程,该线程执行的任务是加法运算。新线程执行的任务是在闭包内部完成的,因此可以避免竞争条件。最后,闭包返回的结果被返回到调用它的上下文中,并通过线程对象被其他线程访问。

上面的代码其实还有很多可以改进的点

  1. 在函数内部创建线程对象应该放在函数外部,否则每次调用函数都会创建一个新的线程对象,导致资源浪费。
  2. 在函数内部创建闭包存储线程对象没有必要,因为线程对象可以直接在函数外部访问。
  3. 函数返回的结果应该是异步执行的,因为在新线程中执行,而主线程直接返回了结果。可以使用回调函数或者Promise解决这个问题。
  4. 最后一行输出结果时,应该输出函数返回的结果,而不是result变量,因为result变量在函数外部是无法访问的。

更新代码如下

// 在函数内部创建一个新的闭包,用于存储线程对象
var thread = null;
function addNumbers(a, b, callback) {  
    function worker() {  
var result = a + b; callback(result); 
    }  
    if (!thread) { 
thread = new Thread(worker); 
thread.start(); 
    } 
    else thread.run(worker); 
}
// 在函数外部创建一个新的线程,并使用闭包创建一个新的线程对象
addNumbers(1, 1, function(result) { 
console.log(result); 
});

闭包的作用

实现私有变量和方法,以及实现高阶函数等功能。但是过度使用闭包也可能导致内存泄漏和性能问题,因此需要慎重使用