这是你理解的闭包吗?

207 阅读2分钟

js闭包的简单理解

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

我们可能经常时候闭包,只是你未发现这是闭包而已罢了。

理解闭包只需要学会三个基本的事实。

第一个事实:JavaScript允许你引用在当前函数以外定义的变量。

 function sayHi() {
   let Hi = "Hi"
 ​
   function name(name) {
     return Hi + "," + name
   }
   return name("罗老师")
 }
 let result = sayHi()
 console.log(result) // Hi,罗老师

第二个事实:即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。

如果这听起来让人难以置信,请记住,JavaScript的函数是第一类(first-class对象)。这意味着,你可以返回一个内部函数,并在稍后调用它。

 function sayHi() {
   let Hi = "Hi"
 ​
   function name(name) {
     return Hi + "," + name
   }
   return name
 }
 let result = sayHi()
 let a = result("a老师")
 let b = result("b老师")
 console.log(a) // Hi,罗老师
 console.log(b) // Hi,罗老师

和第一个例子不同的是,不是在外部调用函数 sayHi 中立即调用 name("罗老师"),而是返回 name 函数本身。因此变量 a 的值是内部的 name 函数,调用变量 a 实际上是调用了 name 函数。但即使 sayHi 函数已经返回,name 函数仍然能记住 Hi 变量的值

学习闭包的第三个也是最后一个事实 : 闭包可以更新外部变量的值。

实际上,闭包存储的是外部变量的引用,而不是它们的值的副本。因此,对于任何具有访问这些外部变量的闭包,都可以进行更新。一个简单的惯用法 box 对象说明了这一切。它存储了一个可读写的内部值。

 function box() {
   let value = undefined;
   return {
     set:function(newValue){value=newValue},
     get:function(){return value},
     type:function(){return typeof value}
   }
 }
 let result = box();
 console.log(result.type()) //undefined
 console.log(result.get()) //undefined
 result.set(100)
 console.log(result.get()) // 100 
 console.log(result.type()) // number

这个例子产生了一个包含三个闭包的对象。这三个闭包是set、get 和 type 属性。它们都共享访问 value 变量。set 闭包更新 value 的值,随后调用 get 和 type 查看更新的结果。

总结

  1. Javascript 允许你引用当前函数以外定义的变量
  2. 即使外部函数已经返回,当前函数仍可以引用在外部函数所定义的变量
  3. 闭包可以更新外部变量的值。实际上,闭包存储的是外部变量的引用,而不是它们的值的副本