[Effective JavaScript 筆記] 第11條:熟練掌握閉包


理解閉包三個基本的事實

第一個事實:js允許你引用在當前函數以外定義的變量。

function makeSandwich(){

      var magicIngredient=”peanut butter”;

      function make(filling){

                return magicIngredient+’and ’+filling;

      }

      return make(‘jelly’);

}

makeSandwich();//”peanut butter and jelly”

圖上直接指出如下

image

第二個事實:即使外部函數已經返回,當前函數仍然可以引用在外部函數所定義的變量。

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”

還是上圖標識

image

原理:js的函數值包含了比調用它們時執行所需要的代碼還要多的信息。而且js函數值還在內部存儲它們可能會引用的定義在其封閉作用域的變量。那些在其所涵蓋的作用域內跟蹤變量的函數被稱為閉包。make函數就是一個閉包。其代碼引用了兩個外部變量:magicIngredient和filling。每當make被調用時,其代碼都能引用到這兩個變量,因為該閉包存儲了這兩個變量。

函數可以引用在其作用域內的任何變量,包括參數和外部函數變量。

function sandwichMaker(magicIngredient){

            function make(filling){

                   return magicIngredient+”and ”+filling;

             }

             return make;

}

var hamAnd=sandwichMaker(“ham”);

hamAnd(“cheese”);//”ham and cheese”

hamAnd(“mustard”);//”ham and mustard”

var turkeyAnd=sandwichMaker(“trukey”);

turkeyAnd(“Swiss”);//”trukey and Swiss”

turkeyAnd(“Provolone”);//”trukey and Provolone”

 

閉包是js最優雅、最有表現力的特性之一,也是許多慣用法的核心。js還提供了一種更為方便構建閉包的字面量語法--函數表達式。

function sandwichMaker(magicIngredient){

              return function(filling){

                     return magicIngredient+”and ”+filling;

             }

}

請注意,該函數表達式是匿名的。由於只需要產生一個新值,而不需要在局部使用,所以沒必要給該函數命名。

 

第三個事實:閉包可以更新外部變量的值。

實際上,閉包存儲的是外部變量的引用,而不是它們的值的副本。因此任何具在訪問這些外部變量的閉包,都可以進行更新。

function box(){

       var val=undefined;

       return {

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

             get:function(){return val},

             type:function(){return typeof val}

       }

}

var b=box();

b.type();//”undefined”

b.set(98.6);

b.get();//98.6

b.type();//”number”

這個例子里產生了一個包含三個閉包的對象。這三個閉包是set,get和type屬性。它們共享訪問val變量。

提示

  • 函數可以引用定義在其外部作用域的變量
  • 閉包比創建它們的函數有更長的生命周期
  • 閉包在內部存儲其外部變量的引用,並能讀寫這些變量

后記

這個部分,這覺得這里講得已經很清楚,如果想再深入去了解,可以去看高3上面關於閉包的講解。

里面對作用域鏈,執行環境,變量對象,都有詳細說明。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM