2011-02-13 44 views
2
var a = (function(y,x) { 
    var x = null; 
    return { 
     foo: function(x){ return this.bar(x * y); }, 
     bar: function(x){ return x + y; } 
    } 
})(3,4); 

請問有人能夠解釋我上面的代碼到底發生了什麼嗎?我可以在哪裏閱讀或參考高級JavaScript技術?對不起,我剛剛開始學習JavaScript。此JavaScript代碼中使用了什麼技術?

回答

1

發生什麼事是您創建了一個匿名函數,它需要2個參數x和y。匿名函數立即執行。

它創建一個局部變量x並將其指定爲空。這個例子中完全沒有意義。 ,並在那裏證明參數x覆蓋本地實例化的x,並且只能使用 this關鍵字訪問。

匿名函數然後返回一個具有屬性foo和bar的對象,這兩個函數都帶有參數x

什麼是最有趣的是,從匿名函數的參數y變成「鎖定」的foo和酒吧的功能裏面,所以,當你撥打:

a.foo(4); // output 15 
a.foo(2); // output 9 

在上面的例子中,4傳遞到函數foo作爲參數x。產品4和3的原始y值在匿名函數中傳遞的是12.該產品被傳遞到條函數中,其中12被添加到相同的鎖定值y的值3中,這會給出總和15.

foo(2)發生同樣的過程。

我的建議是使用Firebug將Firefox拉出並粘貼到控制檯並運行它。然後用不同的值調用a.fooa.bar並追蹤執行情況。這將幫助你更好地理解代碼中發生了什麼。

細分功能的執行與替代:

a.foo(4); 
function(4) { return this.bar(4 * 3); } 
function(4) { return function(4 * 3) { return (4 * 3) + 3; } }; 

function(4) { return function(12) { return (12) + 3; } }; 
function(4) { return function(12) { return 15; }); 

function(4) { return 15; } 
15 

我也建議你看看this example of closures,但沒有匿名函數。刪除匿名組件可能有助於使其更加清晰。

其實,這裏就是你們的榜樣上面,但沒有匿名函數:

function fooBar(y,x) { 
    var x = null; 
    return { 
     foo: function(x){ return this.bar(x * y); }, 
     bar: function(x){ return x + y; } 
    } 
} 

var b = fooBar(3,4); 


b.foo(2); // output 9 
b.foo(4); // output 15 

所以在上面的例子中,fooBar(3,4)返回一個包含兩個函數foo和酒吧的一個對象,鎖定爲3 y參數。

JavaScript Kit - Closures 101. They're Not Magic,是另一個很好的資源,這將有助於解釋封鎖的目的,以及這意味着什麼幕後。

+0

發生你能澄清什麼可以用這個關鍵字(2.段)訪問嗎? –

+0

@Sime - 我要刪除那部分。我不知道的'變種的100%×= null'不是事實,這看似對的函數的結果沒有影響,無論是目前使用var,沒有VAR或完全忽略其他。 – jmort253

+0

非常感謝您的回答,併爲我提供了關閉的鏈接。 – manraj82

6

這是關閉。

創建一個匿名函數,然後立即執行,並將其返回值分配給a

傳遞給它的變量呈現(或多或少)不能被來自其他函數的干擾所訪問。

出於某種原因,x=4立即被外部函數中的x=null覆蓋。然後在每個內部函數的參數中再次重寫。這首先使它毫無意義地通過它。

+0

+1真。無論如何,匿名函數中的'x'的意義是什麼,它在函數的第一行被設置爲'null'? – JCOC611

+0

@ JCOC611:它似乎與'x'參數衝突。不確定它是一個錯字還是一些JavaScript範圍shenanigan? – BoltClock

+0

這就是我要說的。每次都將「x」參數設置爲空。 – JCOC611

0

http://jibbering.com/faq/notes/closures/ - 這解釋了一個可讀的方式的細節。

這種「雙重約束」,因爲只有新的功能領域引入新的執行上下文(見上面的鏈接,這意味着什麼:-)這僅僅是ECMAScript中是如何工作的需要 - 在語言,如C,Java的或C#,每個新塊[一般來說]引入一個新的詞法變量範圍。

編輯(仔細檢查):

var a = (function(y,x) { 
    // This is a new function body, so it introduces a new lexical scope 
    // The following line is questionable. Function parameters always belong to 
    // the function scope. It has the same effect a `x = null` (no var) here 
    // but since it just discards the value, is still questionable... 
    var x = null; 
    return { 
     // Both of these functions have their own function scope and 
     // since they are created here they can "bind" to free variables 
     // in the enclosing scope through the [[scope]] chain (implicitly). 
     // Inside the x refers to the parameter passed in, respectively 
     // and does NOT refer to the x above. 
     foo: function(x){ return this.bar(x * y); }, 
     bar: function(x){ return x + y; } 
    } 
})(3,4); 
// Then the function is executed which results in the object that contains 
// foo and bar properties which contain functions that "close over" y. 

並用相同的語義的清理後的版本,以顯示哪些變量綁定真的發生

var a = (function(y,__ignored) { 
    return { 
     foo: function(x){ return this.bar(x * y); }, 
     bar: function(x){ return x + y; } 
    } 
})(3,4); 
+0

我不會把這個鏈接給初學者,特別是不會把它稱爲可讀性。它進入了JS引擎和激活對象的內部工作。它更多的是關閉如何工作,而不是如何使用。 – mwilcox

+0

@mwilcox我猜可讀是有條件的/主觀的:-)它比規範更可讀 - 但絕對不是「溫和的教程」。 – 2011-02-13 21:58:07

相關問題