2015-10-29 46 views
3

我有以下代碼:使用Javascript - 無法理解的封閉

function bird(type) { 
    return function (whattosay) { //return the whole function 
     console.log (type + ' ' + whattosay) 
    } 

} 

var birdRef = bird('blackbird'); 
birdRef('singing in the dead of night'); 

var secondRef = bird('whitebird'); 

birdRef('singing after that night'); 

我試圖讓熟悉的兩個概念,關閉和作用域鏈。 那麼,在我的第一個birdRef中,我得到一個新的函數對象,然後在該行之後調用它。最後,我在控制檯上看到「夜深人靜的黑鳥在唱歌」。我明白爲了找到鳥類型var,閉包給了你一個父對象的引用,並且它在作用域鏈中有點尋找那個var並最終找到它,所以我們可以看到它的類型。

那麼,你有這樣的:

var secondRef = bird('whitebird'); 

一個新的說法已經過去了,所以現在的VAR「類型」中的鳥函數改爲從黑鳥到whitebird。

現在我回來我以前創建的函數birdRef,我不明白的是,接下來會發生什麼:

birdRef('singing after that night'); 

我得到的,而不是whitebird「那一夜後黑鳥唱歌」。那麼,如果我沒有弄錯,birdRef函數是不是它的父函數bird,並且讀取了更新的bird變量的類型(我的意思是他在當地環境中找不到那個var,所以他看着外面的環境,並發現變種「類型」)?

對不起,如果我沒有多少意義,因爲我是新手,並感謝您的時間。

+0

不,每個函數調用都會創建一個具有不同'type'變量的新上下文(環境)。 'birdRef'和'secondRef'是兩個不同的函數對象,它們關閉了兩個不同的變量。 – Bergi

+0

因此,每個鳥類函數調用都會創建一個適合調用者的新鳥類函數? – RunningFromShia

+0

正確,每個'bird()'返回一個新的函數(使用相同的代碼但不同的上下文) – Bergi

回答

2

您第二次調用第一次關閉的結果。

以下行:

birdRef('singing after that night'); 

應該是:

secondRef('singing after that night'); 

我已經包含了工作演示以下。

function bird(type) { 
 
    return function (whattosay) { //return the whole function 
 
     console.log (type + ' ' + whattosay) 
 
    } 
 

 
} 
 

 
var birdRef = bird('blackbird'); 
 
birdRef('singing in the dead of night'); 
 

 
var secondRef = bird('whitebird'); 
 
secondRef('singing after that night'); 
 
// ^^ secondRef instead of birdRef 
 

 
// Test is again. 
 
birdRef('singing in the dead of night'); 
 
secondRef('singing after that night');

由於type是函數調用的詞法範圍內定義的,它不是詞法作用域的外部訪問。如上所示,除非變量在其定義的詞彙範圍內被修改,否則不能被訪問或修改。

+0

爲了查看鳥類型是否因前面的代碼行secondRef而改變,我第二次將birdRef放入。這個想法是看它是否會影響birdRef函數,因爲birdRef在範圍鏈中上升,並試圖找到最近由secondRef更改的「type」var。 – RunningFromShia

+1

不,它不會超出範圍鏈,因爲type是在分配給bird關鍵字的外部函數聲明創建的詞法範圍內聲明的。因爲每次你調用bird時,它都會創建一個新的詞法作用域,然後在其中創建返回的函數。 –

+0

我寫了[演示](http://jsbin.com/rixusoyira/2/edit?js,console)希望能給你更好的理解。基本上,當您將關鍵字添加到函數的參數列表中時,該關鍵字將標識可在以下作用域內使用函數調用中傳遞的值訪問的變量。它與您在函數範圍內使用var關鍵字定義變量併爲其分配一個靜態值相同。 –