2011-01-09 23 views
7

有沒有辦法在JavaScript中很容易打破封閉?我已經得到了最接近的是這樣的:如何突破封鎖在JavaScript

var src = 3; 
function foo() { 
    return function() { 
     return src; } 
    } 
function bar (func) { 
    var src = 9; 
    return eval('('+func.toString()+')')(); // This line 
} 
alert(bar(foo())); 

此打印「9」,而不是「3」,作爲一個封閉將決定。但是,這種方法對我來說似乎很難看,有沒有更好的方法?

+5

究竟爲什麼你需要做到這一點? O_o –

+0

你想達到什麼目的?你所描述的東西似乎是完全錯誤的想要做的事情。 –

+5

天哪,你是從字面上衝擊的JavaScript的最好的部分,其最糟糕的....我現在哭的權利; _; -1 –

回答

1

正如其他人所說,這似乎不是正確的做法。你應該解釋你爲什麼想要這個以及你想達到什麼目的。

無論如何,一種可能的方法可能是訪問函數內部對象的屬性。例如:

var src = 3; 

function foo (context) { 
    context = context || window; // Fall back to the global namespace as default context 

    return function() { 
     return context.src; 
    } 
} 

function bar (func) { 
    var context = {src: 9}; 
    return func(context); 
} 

alert(bar(foo)); 
+0

閒逛我想這意味着「不要用瓶蓋。」,並改用對象。這可能是我必須做的。我想我可以嘗試傳遞參數函數,然後使用with語句,就像那樣醜陋。 –

+0

這並不意味着「不要使用閉包」。關閉很好。如果您的問題中的代碼是試圖解決實際問題,那麼您似乎還沒有明白它們的用途。 – Jakob

+0

我知道什麼是封閉的,但我需要從文件編譯的代碼,並用它在其他地方,同時有機會獲得私有變量。 –

1

如果您想訪問更廣泛的範圍內的變量,只是不要在較窄範圍內重用變量名稱。

這就是它是如何工作的。與它一起工作,而不是試圖與之對抗。

8

您的代碼沒有打破關閉,您只是將代碼組合成一個函數並在不同的上下文中進行評估(其中標識符src具有不同的值)。它與您在原始src上創建的封閉沒有任何關係。

無法檢查已在封閉中捕獲的數據。從某種意義上來說,這些數據比Java,C++,C#等私有成員更「私有」,無論如何你總是可以使用反射或指針魔術來訪問它們。

2

如果您嘗試在循環中創建多個相似的方法,這可能很有用。例如,如果您要在依賴循環變量的循環中創建點擊處理程序,以便在每個處理程序中執行一些不同的操作。 (我已經刪除了「eval」,因爲它是不必要的,通常不應該使用)。

// Assign initial value 
var src = 3; 

// This is the regular js closure. Variables are saved by reference. So, changing the later will 
// change the internal value. 
var byref = function() { 
    return src; 
} 

// To "break" the closure or freeze the external value the external function is create and executed 
// immidiatly. It is used like a constructor function which freezes the value of "src". 
var byval = function(s) { 
    return function() { return s }; 
}(src); 

src = 9; 

alert("byref: " + byref()); // output: 9 
alert("byval: " + byval()); // output: 3 
0

這裏的代碼看看你是否可以理解循環中定義的閉包。

var clicked = false; 
for(var i=0;i<temp.length;i++){ 
    (function(index){ 
    if(clicked) return false; 
    $(temp[index]).on('click',function(){ 
    if($(temp[index]).text()=="" && !$(".cell1").val()){ 
     $(this).text(player1Val); 
     $(".cell1").val(true); 
     console.log("first player clicked "); 
     clicked = true; 
     $(this).off(); 
     for(var j=0;j<temp.length;j++){ 
      $(temp[j]).off('click'); 
     } 
     return false; 
    } 
    else return false; 
    }); 
})(i); 
}