如何理解闭包

闭包是 JavaScript 中一个非常重要的概念,理解它的原理和使用方法对于编写高质量的 JavaScript 代码非常重要。

# 什么是闭包

JavaScript 中的闭包是指函数能够访问其定义外部作用域的能力。具体来说,当函数内部引用了外部函数中的变量时,它会创建一个闭包,保存对该变量的引用, 使得即使外部函数已经执行完毕,该变量仍然可以在内部函数中访问。

# 闭包的应用

闭包在 JavaScript 中有很多应用,例如实现模块化、缓存值、实现私有变量等。它们能够帮助我们编写更加健壮和灵活的代码。

# 模块化

在这个例子中,我们使用一个立即执行函数来创建一个模块。函数中有两个私有成员:privateVar 和 privateFunc。这些成员是通过闭包来实现私有作用域的,因此外部代码无法直接访问它们。

我们还暴露了两个公共成员:publicVar 和 publicFunc。这些成员可以被外部代码访问,并且可以使用私有成员。当我们调用 publicFunc 方法时,它将输出一些文本,并调用私有函数 privateFunc。

最后,我们将整个模块赋给一个变量 module。由于该模块是在一个立即执行函数中定义的,因此其内部成员将不会污染全局命名空间。

var module = (function() {
  var privateVar = "I'm private";
  
  function privateFunc() {
    console.log("This is a private function");
  }
  
  return {
    publicVar: "I'm public",
    
    publicFunc: function() {
      console.log("This is a public function");
      console.log(privateVar);
      privateFunc();
    }
  };
})();

console.log(module.publicVar); // 输出 "I'm public"
module.publicFunc(); // 输出 "This is a public function","I'm private" 和 "This is a private function"
console.log(module.privateVar); // 输出 undefined
module.privateFunc(); // 抛出一个错误,因为 privateFunc 是未定义的

# 缓存值

下面这个函数可以缓存相同参数的执行结果并直接返回。

const power = x=>{
    console.log(x)//测试缓存
   return  x*x
}

const memozie = (f)=>{
	let cache ={}
	return function (){
		let k = JSON.stringify(arguments)
		cache[k] =cache[k]||f.apply(f,arguments)
     return  cache[k]
	}
}

const cachePower = memozie(power)

console.log(cachePower(5)) // 5 25
console.log(cachePower(5)) //  5

# 私有变量

以下实现了一个只执行一次的函数。类似JQuery中的once函数

const once = ()=>{
    let done = false
    return function (f) {
        if(!done) f()
        done =true
    }
}
function counter() {
  let count = 0;

  function increaseCount() {
    count++;
    console.log(count);
  }

  return increaseCount;
}

const myCounter = counter();

myCounter(); // 输出 1
myCounter(); // 输出 2
myCounter(); // 输出 3

在这个例子中,counter函数返回一个内部函数increaseCount。count变量只能通过increaseCount函数访问,并且无法从外部直接访问。

通过每次调用increaseCount函数来增加count的值,并且使用闭包的方式保持了count的状态,因此每次调用myCounter()时,count的值都会增加。

这种方法利用了JavaScript的作用域规则,以便将变量隐藏在闭包中,从而实现私有变量的效果。

注意

在使用闭包时,我们需要注意内存管理问题。如果闭包引用了大量的外部变量或者被保存了很长时间,可能会导致内存泄漏,从而影响程序性能。 因此,在使用闭包时,我们需要谨慎处理内存管理,确保及时释放不再需要的引用。

function createList() {
  let items = [];

  return {
    addItem: function(item) {
      items.push(item);
    },
    getItems: function() {
      return items;
    }
  };
}

const myList = createList();
myList.addItem('item 1');
myList.addItem('item 2');
console.log(myList.getItems());

// 假设这里不再需要myList,但是由于闭包的存在,items数组仍然在内存中占用空间

为了避免这种问题,我们可以手动清除不再需要的闭包。

在这个例子中,我们可以将myList设置为null,以便JavaScript垃圾回收机制可以清除与createList相关的内存。

最近更新
01
echarts扇形模拟镜头焦距与可视化角度示意图
03-10
02
vite插件钩子
03-02
03
vite的依赖预构建
02-13
更多文章>