2011-01-09 12 views
7

Gibt es eine Möglichkeit, eine Schließung in JavaScript leicht zu brechen? Die nächstgelegene ich bekommen habe, ist dies:Wie man Verschlüsse in JavaScript bricht

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

Diese Drucke ‚9‘, statt ‚3‘, wie ein Verschluss diktieren würde. Dieser Ansatz erscheint mir jedoch irgendwie hässlich. Gibt es bessere Möglichkeiten?

+5

Warum sollten Sie das jemals tun? O_o –

+0

Was möchten Sie erreichen? Was Sie beschreiben, scheint nur eine völlig falsche Art zu sein, etwas zu tun zu wollen. –

+5

Gosh, du sprichst buchstäblich den besten Teil von JavaScript mit seinem schlimmsten Teil ... Ich weine gerade jetzt; _; -1 –

Antwort

1

Wie andere sagten, scheint dies nicht das Richtige zu sein. Sie sollten erklären, warum Sie dies wollen und was Sie erreichen möchten.

Wie auch immer, ein möglicher Ansatz könnte sein, auf Eigenschaften eines Objekts in Ihrer Funktion zuzugreifen. Beispiel:

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

Ich denke, das bedeutet "benutze keine Verschlüsse.", und stattdessen Objekte zu verwenden. Was ich vielleicht machen muss. Ich denke, ich könnte versuchen, eine Argumentfunktion zu übergeben und dann eine With-Anweisung zu verwenden, so hässlich wie das wäre. –

+0

Es bedeutet nicht "keine Verschlüsse verwenden". Verschlüsse sind großartig. Es scheint nur so, als hättest du noch nicht verstanden, wofür sie sind, wenn der Code in deiner Frage ein Versuch ist, ein echtes Problem zu lösen. – Jakob

+0

Ich weiß, was Schließung ist, aber ich muss Code aus einer Datei kompilieren und woanders verwenden, während ich Zugriff auf private Variablen habe. –

1

Wenn Sie auf eine Variable in einem größeren Bereich zugreifen möchten, verwenden Sie den Variablennamen nicht in einem engeren Bereich.

So soll es funktionieren. Arbeite damit, anstatt zu versuchen, dagegen anzukämpfen.

8

Ihr Code bricht die Schließung nicht, Sie nehmen nur den Code, der eine Funktion ausmacht, und werten ihn in einem anderen Kontext aus (wobei der Bezeichner src einen anderen Wert hat). Es hat nichts mit der Schließung zu tun, die Sie über das Original src erstellt haben.

Es ist nicht möglich, Daten zu prüfen, die in einer Schließung erfasst wurden. In gewissem Sinne sind solche Daten sogar "privater" als private Mitglieder in Java, C++, C# usw., wo Sie immer mit Reflektions- oder Zeigermagie auf sie zugreifen können.

2

Dies kann nützlich sein, wenn Sie versuchen, mehrere ähnliche Methoden in einer Schleife zu erstellen. Zum Beispiel, wenn Sie einen Click-Handler in einer Schleife erstellen, die auf einer Loop-Variable beruht, um etwas in jedem Handler etwas anders zu machen. (Ich habe das "eval" entfernt, weil es unnötig ist, und sollte in der Regel nie verwendet werden).

// 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

Hier ist der Code zu sehen, wenn Sie verstehen können, Verschlüsse innerhalb einer Schleife definiert.

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); 
}