Code kapseln?

DataFox

Erfahrenes Mitglied
Hallo ihr Lieben!

ich habe neulich mal bei einer Unterhaltung zwischen zwei Javascript-Freaks gehört, das man seine Skripte immer kapseln muss, wenn sie auch von fremden verwendet werden sollen. Ich bekam nicht die Gelegenheit da mal nachzuhaken was die damit meinen.

Also es ging wohl um Namenskollisionen z.b. von Functions und Vars. Denn es könnte ja durch einen dummen Zufall sein, das ein fremdes Skript die gleichen Namen benutzt, und es dann kollidiert. Nur das mit dem kapseln, was genau ist das? Wenn ich das Skript auslagere haben andere Skripte aus anderen Dateien innerhalb des Documents immer noch Zugriff auf alle globalen Variablen und Functions.

Kann mir jemand kurz ein Beispiel nennen was man unter "Kapselung eines Skriptes" versteht?

besten dank!
Laura
 
Naja man kann in JS Pseudo OOP programmieren dazu hat man gewisse Möglichkeiten.

Innerhalb einer Funktion kann man Variablen lokal definieren , das ist des var varname.
Auf die hast von aussen schon mal keinen Zugriff mehr.

Code:
function foobar () {
   var name = 'klaus';
}

alert(name); // wird eine Fehlermeldung geben.
var foo = new foobar () ;
alert(foo.name); // wird auch nicht funktionieren

aber

Code:
function foobar () {
   this.name = 'klaus'; // diese Variable ist nur innerhalb der Funktion sichtbar 
                                // aber man kann von aussen auf sie zugreifen wenn 
                                // man eine Instanz von foobar anlegt
}

alert(name); // wird uns auch wieder um die Ohren fliegen
var foo = new foobar();
alert(foo.name); // wirft uns klaus an den Kopf

Das gleiche Spiel funktioniert auch so mit Funktionen auch Closures genannt , Closures sind Funktionen in Funktionen.

Code:
function foobar () {
    var name = null;    
 
    function toUpper (n) {
        return n.toUpperCase();
    }
  
     this.setName = function (n) {
        // hier haben wir zugriff auf die Variable name
        name = toUpper(n);
    }

    this.getName = function () {
       return name;
    }
}

var test = new foobar();
test.toUpper(); // nix da kommen wir nicht dran 
test.setName('klaus');
alert(test.getName('klaus');
alert(test.name); // kommen wir auch nicht ran

da gibt es noch ne menge weitere Spielerein "statische Klassen" zum Beispiel. Auf den Wege kann man auch Singleton Patterns realisieren.

Code:
var foobar = (function () {
    var name = null;

    function toUpper(n) {
        return n.toUpperCase();
    }

    return {
        setName:function (n) {
            name = toUpper(n);
        },
        getName:function() {
           return name;
        }
    }
})();

var foo = new foobar(); // das wird nicht mehr funktionieren nun 
// aber 
foobar.setName('herbert');
alert(foobar.getName()); // gibt uns HERBERT zurück
foobar.setName('klaus');
alert(foobar.getName()); // gibt uns KLAUS zurück nun herbert ist weg

// auf name und toUpper haben wir immer noch keinen zugriff

Vererbung wäre auch möglich

Code:
function WriteBig () {
    this.toUpper = function (n) {
         return n.toUpperCase();
    }
}

function Name () {
    var name = null;
    var thisObj = this;

    this.setName = function (n) { 
         name = thisObj.toUpper(n);
    }

   this.getName = function () {
       return name;
   }
}
Name.prototype = new WriteBig();

var test = new Name();
test.setName('klaus');
alert(test.getName()); // gibt uns KLAUS wieder

Was das OOP in JS angeht gibt es auch einige Seiten online , Wikepdia ist ne ganz gute und andere Seiten im Netz.

Einfach mal nach Prototyping , OOP JavaScript suchen findet man eigentlich ne ganze Menge.

MfG
 
Hi

ich habe da mal was gebastelt...

Code:
var globaleVariableDieUeberallSichtbarSeinSoll = "hallo";

function foo() {
	var name = "Hai";
	
	this.getName = function() {
		return name;
	}
}

function bar() {
	var name = "Fisch";
	
	var test2 = new foo();
	
	this.getName = function() {
		return name;
		//return test2.getName();
	}
}

var test = new bar();
alert(test.getName());

Wie stelle ich es an, das meine globaleVariableDieUeberallSichtbarSeinSoll z.B. innerhalb von bar() oder foo() sichtbar ist? Muss ich diese Variable ebenfalls in einer Function unterbringen?

Gruß
Laura
 
var globaleVariableDieUeberallSichtbarSeinSoll = "hallo"; die ist schon überall sichtbar , wobei ich eben selber noch gestaunt habe.

Code:
var globi = "hallo welt";

function test() {
   alert(globi); // gibt wie erwartet hallo welt aus
}
test();
alert(globi); // gibt immer noch hallo welt aus

aber

Code:
var globi = "hallo welt";

function test() {
   alert(globi); // das ergibt undefined weil die Variable innerhalb der Funktion neu definiert 
                    // wird und da JavaScript nur nen Interpreter hat kennt JS die noch nicht
                    // bei Java würde es klappen so würde ich mir dieses Verhalten
                    // einfach mal erklären
   var globi = "hallo sonne"; // globi ist nur innerhalb der Funktion sichtbar
   alert(globi); // hallo sonne 
}
test();
alert(globi); // gibt hallo welt aus

ebenfalls

Code:
   function test() {
        globi = "huhu"; // variable als Global gebranntmarkt kann Sichtbarkeitsbereich 
                              // erweitert sich da kein var vor globi steht
  }
  alert(globi) // gibt huhu aus
 
Interessant!

Aber mir ist auch noch etwas seltsames aufgefallen... oder ich habe Tomaten auf den Augen:

function machWas() {
function tuDas(zahl) {
alert("input: " + zahl);
}
window.setInterval("tuDas(-1)",2500);
}
machWas();

geht nicht! "Objekt erwartet!" kommt da...
Aber:

Code:
function machWas() {
	this.tuDas= function(zahl) {
		alert("input: " + zahl);
	}
	window.setInterval("tuDas(-1)",2500);
}
machWas();

funktioniert... warum ist das so?

Gruß
Laura
 
Gute Frage nächste Frage , aber man hat bei setInterval 2 möglichkeiten den Code zu übertragen.

Da lerne ich auch noch hinzu , also wenn man sich folgendes anschaut:

Code:
            function test (callback) {
                if(typeof callback != 'function') {
                    alert(this.name); // gibt hannes aus warum auch immer
                    eval(callback);
                } else {
                    callback.call(callback);
                }
            }
              
            function check () {
                function tudas() {
                    alert("woooot");
                }
                this.name = "hannes";
                
                test("tudas()"); // die funktion wird er nicht finden aber er wird in der Funktion 
                                      // test auf einmal den Namen Hannes ausgeben können
            }           
            check();

Wieso ? kA mehr ;)

Aber wenn man in die Doku schaut hast genau 2 Möglichkeiten setInterval zu füttern.

1. ist einen String anzugeben welcher immer ausgeführt werden soll in ein gewissen zeitinterval das ist ja dann der Funktionsaufruf.
2. man gibt eine Funktion mit auf den Weg

Code:
   function machWas () {
       function tuDas (zahl) {
            alert(zahl);
       }
       window.setInterval(function () { tuDas(-1) },2500);
   }

Wie sich das mit dem this und den Funktionsaufrufen genauer aufbaut da hab ich nun leider auch keine Ahnung mehr :/ Könnnte man sich eventuell ja mal Gedanken dazu machen.
 
na ja, hauptsache man weis wie man es machen muss ;)

Aber jetzt stecke ich richtig fest. Ich vereinfache es mal stark:

Code:
// Gekapselt: Standardfunktionen (muss separat sein!)
function StandardFuncs() {
	this.addEvent = function(eo, eventType, function_name) {
		if (eo.addEventListener) {
			eo.addEventListener(eventType, function_name, false);
		} else if (eo.attachEvent) {
			eo.attachEvent("on"+eventType, function_name);
		}
	}
}


function MeinScript() {
	var SF= new StandardFuncs();
	SF.addEvent(window.document, 'click', documentClickEventFunction);
	this.documentClickEventFunction = function(e) {
		alert('click!');
	}
}
var MScr = new MeinScript();

Ich bekomme eine Fehlermeldung: "documentClickEventFunction ist Null oder kein Objekt"

Die wird in der addEvent-Func von StandardFuncs ausgelöst. Klar: Weil dort die documentClickEventFunction unbekannt ist. Ich dachte hier entsteht automatisch so eine Art "Querverbindung" zwischen den beiden. Aber niente.

Dann habe ich probiert ein this. davor zu stellen:

Code:
// Gekapselt: Standardfunktionen (muss separat sein!)
function StandardFuncs() {
	this.addEvent = function(eo, eventType, function_name) {
		if (eo.addEventListener) {
			eo.addEventListener(eventType, function_name, false);
		} else if (eo.attachEvent) {
			eo.attachEvent("on"+eventType, function_name);
		}
	}
}


function MeinScript() {
	var SF= new StandardFuncs();
	SF.addEvent(window.document, 'click', this.documentClickEventFunction); //this. davor gesetzt...
	this.documentClickEventFunction = function(e) {
		alert('click!');
	}
}
var MScr = new MeinScript();

und es t net :(
Der Browser meldet mir einen "Typkonflikt". Wie kann ich das Dingens an die "fremde" Funktion übergeben? Mit MScr. davor klappts auch nicht, da MScr noch nicht bekannt ist.

Das riecht nach unlösbare Zwickmühle, hab das Gefühl ich kann das so gar ncht machen...hmm

ne Idee?

Gruß
Laura

P.S.: Gerade getestet: Es t auch net, wenn ich die addEvent Funktion direkt in die MeinScript-"Klasse" einbaue :/
 
Zuletzt bearbeitet:
Hi,

du musst documentClickEventFunction im richtigen Kontext aufrufen - nämlich als Methode des Objekts MeinScript.
Code:
function MeinScript() {
  var SF= new StandardFuncs();

  // this-Objekt "closuren"
  var objThis = this;
  // Als drittes Argument eine Funktion übergeben, die die Funktion (documentClickEventFunction)
  // im passenden Kontext aufruft (objThis als Closure für MeinScript-Instanz)
  SF.addEvent(window.document, 'mousemove', function(){objThis.documentClickEventFunction();});

  this.documentClickEventFunction = function(e) {
    alert('click!');
  }
}
var MScr = new MeinScript();


Edit - @FipsTheThief:
function test (callback) {
if(typeof callback != 'function') {
alert(this.name); // gibt hannes aus warum auch immer
eval(callback);
} else {
callback.call(callback);
}
}
Ich denke es wird aus folgendem Grund "hannes" ausgegeben. this läuft sowohl bei der Zuweisung als auch bei der Ausgabe im Kontext des window-Objekts und dieses ist global verfügbar.

Gleicher Grund auch, dass es in Lauras Beispiel mit this funktioniert. In diesem Fall existiert die Funktion im window-Objekt, in dessen Kontext auch die Funktion setInterval aufgerufen wird.


Ciao
Quaese
 
Zuletzt bearbeitet:
Genial, darauf wäre ich heute vermutlich nicht mehr gekommen ;) Danke!

Ich habe gerade auch heraus gefunden, das man es so machen könnte:

Code:
// Gekapselt: Standardfunktionen (muss separat sein!)
function StandardFuncs() {
	this.addEvent = function(eo, eventType, function_name) {
		if (eo.addEventListener) {
			eo.addEventListener(eventType, function_name, false);
		} else if (eo.attachEvent) {
			eo.attachEvent("on"+eventType, function_name);
		}
	}
}


function MeinScript() {
	var SF= new StandardFuncs();
	this.documentClickEventFunction = function(e) {
		alert('click!');
	}
	SF.addEvent(window.document, 'click', documentClickEventFunction);
//und den addEvent von oben nach unten geholt...
}
var MScr = MeinScript(); //hier das "new" weg gelassen!

ich weis jetzt nicht, ob das schlau war. Aber es funktioniert auch :)

Gruß
Laura

--------- Edit --------
@Quaese:
Code:
  // this-Objekt "closuren"
  var objThis = this;

was hat es mit dem "closuren" genauer auf sich? Reicht da nicht einfach "this"? Habe so eine Vermutung, das this irgendwo mal global verfügbar sein kann so das es Probleme / Verwechselungen mit den anderen "thisses" gibt. Deshalb kopieren und lokal begrenzen. Oder?

besten Dank! Ihr habt mir sehr geholfen :)

Gruß
Laura
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück