19 Stimmen

Javascript automatische Getter/Setter (John Resig Buch)

Ich lese "Pro Javascript Techniques" von John Resig und bin mit einem Beispiel verwirrt. Dies ist der Code:

// Erstellt ein neues Benutzerobjekt, das ein Objekt von Eigenschaften akzeptiert
function User( properties ) {
  // Iteriere über die Eigenschaften des Objekts und überprüfe,
  // dass es ordnungsgemäß abgeschirmt ist (wie zuvor besprochen)
  for ( var i in properties ) { (function(){
  // Erstellt ein neues Getter für die Eigenschaft
  this[ "get" + i ] = function() {
    return properties[i];
  };
  // Erstellt ein neues Setter für die Eigenschaft
  this[ "set" + i ] = function(val) {
    properties[i] = val;
  };
})(); }
}

// Erstellt eine neue Benutzerobjektinstanz und gibt ein Objekt von
// Eigenschaften mit, um es zu initialisieren
var user = new User({
  name: "Bob",
  age: 44
});

// Beachte nur, dass die Eigenschaft 'name' nicht existiert, da sie privat ist
// innerhalb des Eigenschaftenobjekts
alert( user.name == null );

// Jedoch können wir auf ihren Wert über die neue getname()
// Methode zugreifen, die dynamisch generiert wurde
alert( user.getname() == "Bob" );

// Schließlich können wir sehen, dass es möglich ist, das Alter zu setzen und abzurufen
// mithilfe der neu generierten Funktionen
user.setage( 22 );
alert( user.getage() == 22 );

Jetzt wirft das Ausführen davon auf der Firebug-Konsole (auf FF3) einen Fehler, dass user.getname() keine Funktion ist. Ich habe versucht, das zu machen:

var other = User
other()
window.getname() --> das funktioniert!

Und es hat funktioniert!

Irgendwelche Ideen warum? Vielen Dank an alle!

PS: Ich empfehle dieses Buch nachdrücklich.

EDIT:

das hier ausführen:

var me = this;

scheint etwas besser zu funktionieren, aber beim Ausführen von "getname()" gibt es '44' zurück (die zweite Eigenschaft)...

außerdem finde ich es seltsam, dass es auf dem window-Objekt ohne Änderung funktioniert hat...

und eine dritte Frage, was ist der Unterschied zwischen PEZ Lösung und dem Original? (er verwendet keine anonyme Funktion)

Danke an alle für das Feedback! +1

2voto

Shidhin Cr Punkte 858

Ich habe den Code gerade ein wenig so geändert.. Das sollte funktionieren.. Das ist dasselbe wie "me=this" setzen; Aber eine Closure ist erforderlich, um den Wert jeder Eigenschaft richtig zu setzen, ansonsten wird allen Eigenschaften der letzte Wert zugewiesen.

// Erstelle ein neues Benutzerobjekt, das ein Objekt mit Eigenschaften akzeptiert
var User = function( properties ) {
  // Gehe die Eigenschaften des Objekts durch und stelle sicher
  // dass es ordnungsgemäß bereichsgebunden ist (wie zuvor besprochen)
  var THIS = this;
  for ( var i in properties ) { (function(i){
    // Erstelle einen neuen Getter für die Eigenschaft
    THIS[ "get" + i ] = function() {
      return properties[i];
    };
    // Erstelle einen neuen Setter für die Eigenschaft
    THIS[ "set" + i ] = function(val) {
      properties[i] = val;
    };
  })(i); }
}

// Erstelle eine neue Instanz eines Benutzerobjekts und übergebe ein Objekt mit
// Eigenschaften, um es damit zu initialisieren
var user = new User({
  name: "Bob",
  age: 44
});

// Beachte einfach, dass die Eigenschaft "name" nicht existiert, da sie privat ist
// innerhalb des Eigenschaftenobjekts
alert( user.name == null );

// Wir können jedoch auf ihren Wert zugreifen, indem wir die neue Methode getname()
// verwenden, die dynamisch generiert wurde
alert( user.getname() == "Bob" );

// Schließlich können wir sehen, dass es möglich ist, das Alter mit den
// neu generierten Funktionen zu setzen und abzurufen
user.setage( 22 );
alert( user.getage() == 22 );

1voto

PEZ Punkte 16398

Vielleicht ist die Variable i mit dem letzten Wert in der Iteration ("age") "geschlossen"? Dann werden alle Getter und Setter auf properties["age"] zugreifen.

0voto

Pablo Fernandez Punkte 98441

Ich habe etwas gefunden, das die Antwort zu sein scheint, es geht alles um den Kontext. Wenn man die anonyme Funktion innerhalb der Schleife verwendet, ändert sich der Kontext und 'this' bezieht sich auf das Fensterobjekt, seltsam, oder?

also:

function User( properties ) {

  for ( var i in properties ) { 
     // hier ist this == User-Objekt
    (function(){
     // innerhalb dieser anonymen Funktion ist this == Fensterobjekt
    this[ "get" + i ] = function() {
      return properties[i];
    };

    this[ "set" + i ] = function(val) {
      properties[i] = val;
    };
    })(); 
  }
}

Ich weiß nicht, warum diese Funktion den Ausführungskontext ändert, ich bin mir nicht sicher, ob das so sein sollte, aber du kannst es testen, indem du den Code dort ausführst und window.getname() versuchst - und es funktioniert magischerweise! :S

Die Lösung, wie bereits erwähnt, besteht darin, den Kontext zu ändern. Das kann, wie J Cooper sagte, durch Weitergabe der Variable 'me' und Erstellung der Funktion als Closure erfolgen, oder du kannst folgendes tun:

(function(){
     // innerhalb dieser anonymen Funktion ist this == User, weil wir es mit 'call' aufgerufen haben
    this[ "get" + i ] = function() {
      return properties[i];
    };

    this[ "set" + i ] = function(val) {
      properties[i] = val;
    };
 }).call(this); 

Wie dem auch sei, wenn ich 'getname' ausführe, erhalte ich immer noch 44... irgendwelche Ideen?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X