便写高质量JavaSript的68个高效方法 >> 二章:变量作用域 >> 第11条:熟练掌握闭包

二章

第11条:熟练掌握闭包

理解闭包的三个基本事实:

1. javaSricpt允许你引用在当前函数以外定义的变量。

2. 即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。

3. 闭包可以更新外部变量的值。

 

 

1. javaSricpt允许你引用在当前函数以外定义的变量。

复制代码
function makeSandwich(){

  var magicIngredient = "peanut butter";

  function make(filling){

    return magicIngredient + "and" + filling;

  }

  return make("jelly");

}

makeSandwich();      //"peanut butter and jelly"
复制代码

请注意内部的make函数是如何引用定义在外部makeSandwich函数内的magicIngredient变量的。

2. 即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。

复制代码
function sandwichMaker(){

  var magicIngredient = "peanut butter";

  function make(filling){

    return magicIngredient + "and" + filling;

  }

  return make;

}

var f = sandwichMaker();

f("jelly");    //"peanut butter and jelly"

f("bananas");     //"peanut butter and bananas"

f("marshmallows")     //"peanut butter and marshmallows"
复制代码

与 1 的不同之处:f的值为内部的make函数,调用f实际上是调用make函数。

        即使sandwichMaker函数已经返回,make函数仍能记住magicIngredient的值。

这是如何工作的:JavaScript的函数值包含了比调用他们时执行所需要的代码还要多的信息。而且,JavaScript函数值还在内部存储他们可能会引用的定义在其封闭作用域的变量。那些在其所涵盖的作用域内跟踪变量的函数被称为闭包。

make函数就是一个闭包,其代码引用了两个外部变量:magicIngredient 和filling。每当make函数被调用时,其代码都能引用到这两个变量,因为该闭包存储了这两个变量。

函数可以引用在其作用域内的任何变量,包括参数和外部函数变量。

更加通用的sandwichMaker函数

复制代码
function sandwichMaker(magicIngredient){  
  function make(filling){     
    return magicIngredient + "and" + filling;   
  }   return make; 
} 
var handAnd = sandwichMaker("ham"); 
handAnd("cheese");        //"ham and cheese" 
handAnd("mustard");             //"ham and mystard" 
var turkeyAnd = sandwichMaker("turkey"); 
turkeyAnd("Swiss");    //"turkey and Swiss"
turkeyAnd("Provolone");  //"turkey and provolone" 
复制代码

函数表达式(更方便地构建闭包的字面量语法)

function sandwichMaker(magicIngredient){  
  function make(filling){     
    return magicIngredient + "and" + filling;   
  }  
} 

3. 闭包可以更新外部变量的值。

  实际上,闭包存储的是外部变量的引用,而不是他们的值的副本。

  因此对于任何具有访问这些外部变量的闭包,都可以进行更新。

一个简单的惯用法box对象的例子。(他存储了一个可读写的内部值)

 

复制代码
 function box(){

    var val = unfefined;

     return {

        set:function(newVal){ val = newVal; },

        get:function(){ return val; },
        type:function(){ return val; }
     };
  }

  var b = box();

  b.type();     //"undefined"
  b.set(98.6);     

  b.get();    //98.6
  b.type();     //"number"
这个例子产生了一个包含三个闭包的对象。
这三个闭包是set、get、type属性。他们都共享访问val变量。set闭包更新val的值,随后调用get和type查看更新的结果。
复制代码

提示:

  • 函数可以引用定义在其外部作用域的变量。
  • 闭包比创建他们的函数有更长的生命周期。
  • 闭包在内部存储其外部变量的引用,并能读写这些变量。

 

posted @   小那  阅读(208)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示