2010-11-08 15 views
5

Ich versuche, einige externe JS-Dateien zu laden, und einige unlösbare Namespace-Konflikte haben.kann ich eine Javascript-Datei in einem anderen Kontext als 'Fenster' laden?

Ich hatte die Idee, einige der Dateien in ihrem eigenen Kontext irgendwie zu laden, das "this" vom Zeigen auf das Fensterobjekt zu irgendeinem kundenspezifischen Namensraum zu ersetzen.

Beispiel:

first.js:

name = "first"; 

second.js:

name = "second"; 

Es scheint mir, dass diese Art von Trick sehr nützlich sein kann. Ist es überhaupt möglich?

EDIT
scheint, dass „this“ nicht beginnen, das Problem zu lösen ersetzen, da es nicht die Standardkontext-Kennung für die Auflösung in Javascript ist. das ist mein Testcode:

var first = {}; 
var second = {}; 

(function(){name = "first";}).call(first); 
(function(){name = "second";}).call(second); 


document.write('name= '+name+' <br/>\n'); //prints "second" 
document.write('first.name= '+first.name+' <br/>\n'); //prints "undefined" 
document.write('second.name= '+second.name+' <br/>\n'); //prints "undefined 

irgendwelche ideen?

Lösung
Es ist nicht möglich. Ich bin heute klüger geworden als heute Morgen, und ich gab es auf. Ich empfehle diese erhellende Lektüre für jedermann mit einem ähnlichen Problem, das einen Riss an, es nehmen möchten: http://jibbering.com/faq/notes/closures/
http://softwareas.com/cross-domain-communication-with-iframes

Antwort

2

Auch wenn dies eine alte Frage ist, kann diese Antwort noch für einige relevant sein:

Wenn eine js-Datei automatisch bekommt Kontext des Fensters geladen wird. Das ist nicht möglich zu ändern. Wenn Sie jedoch versuchen, Konflikte zwischen Bibliotheken zu vermeiden, die Sie laden, und Sie haben keine Kontrolle über diese Libs, und sie nicht über einen eingebauten „no-Konflikt“ Mechanismus haben, dann ist es ein schöne Trick - Sie können diese in einen Source-less iframe laden. Das macht ihren Kontext das Fenster des iframe zu sein, und Sie werden noch in der Lage sein, den Iframe zugreifen, da es hier kein domänenübergreifende Thema ist.

Sie können für den Einsatz dieser Technik this library als Beispiel sehen.

+0

Ironischerweise wurde das ursprüngliche Problem ausgelöst, wenn ich mehrere JQuery-Versionen verwalten wollte :). Ich habe am Ende etwas IFrame-Sache gemacht, wenn ich mich genau erinnere. –

-1

gut Sie die Inhalte der js Dateien mit so etwas wie diese wickeln könnte:

var externalInterfaceForYourObject = (function(){ 
    //code that defines your object 

    //this should refer to the current anonymous function, and not the window object 
    return this; 
})(); 
+0

Ich habe es getestet und die anonyme Funktion wird unter dem Fenster Kontext ausgeführt, und senden Sie das Fenster-Objekt. –

1

Sie Ihre Datei in einem iframe laden kann, ist die Datei kein .js sondern eine HTML-Datei, wie:

<html> 
<body> 
    <script> 
    var $ = parent.$, // you can share objects with the parent, eg: jQuery 
     localObject = { // your local object definition 
     name: 'first', 
     showName: function(){ 
      $('div.name').html(this.name); 
     } 
     }; 
    //assign the local object to the custom namespace 
    parent.customNamespace.object1 = localObject; 
    </script> 
</body> 
</html> 

Der Trick besteht darin, parent. zu verwenden, um die JavaScript-Objekte auf der übergeordneten Seite verfügbar zu machen.

+0

Dies scheint wie eine schmutzige, aber machbar Lösung, aber ich kann es nicht aus Gründen verwendet ich nicht in der ursprünglichen Frage angegeben haben - mein Code kommt von außerhalb der Domäne des Dokumenten- und so meine IFrame wird intern nicht die Eltern zugreifen kann Zustand. –

+0

Ich verwende es stark in unserer App, um die 3 Codes sauber zu trennen: HTML, CSS und JS. Ich fand es eine nicht so dreckige Art, Browser-Seite zu enthalten. Wie Sie Cross-Domains sind, denke ich, der einzige Weg ist, Ihren Server die js-Dateien holen, transformieren und zwischenspeichern, umwickeln sie innerhalb einer Funktion übergibt das als Kontext, und senden Sie sie an den Browser zB: 'http: //yourdomain.com/fetchjs? url = http: // otherdomain.com/other.js & namespace = custom.object1' viel Glück. – Mic

+0

Leider ist Server-Seite auch keine Option. Als ich "schmutzig, aber machbar" schrieb, dachte ich an die Prioritäten, die ich beantworten muss - wo die zusätzliche Seitenbelastung als sehr kostspielig angesehen wird. Ich stimme zu, dass Code-and-Order-weise die Lösung am einfachsten zu implementieren und zu pflegen ist. Vielen Dank. –

3

Ich bin nicht klar über Ihren Grund dafür; was verwendest du genau für this?

Wenn Sie den Inhalt Ihrer second.js in einer anonymen Funktion einschließen, wird verhindert, dass Variablen in dieser Datei mit globalen Variablen in Konflikt geraten. Wenn Sie wirklich ein this Satz auf ein bestimmtes Objekt haben muss, die nicht das globale Objekt ist, könnten Sie so etwas wie

var differentThis = {}; 
(function() { 
    // Contents of second.js go here 
}).call(differentThis); 

UPDATE

Sie können nicht tun, was Sie wollen tun. Sie scheinen auf das Variable-Objekt zuzugreifen, das das Objekt ist, zu dem eine Eigenschaft hinzugefügt wird, wenn Sie eine Variable in JavaScript deklarieren. Im globalen Code ist das Objekt Variable das globale Objekt, auf das Sie zugreifen können. Innerhalb einer Funktion ist dies eine Eigenschaft des Ausführungskontexts, auf die nicht direkt zugegriffen werden kann.

+0

Ich habe das schon versucht, und obwohl das "this" -Schlüsselwort richtig ersetzt, fand ich heraus, dass es nicht der Standardkontext für die Identifikatorauflösung ist. –

1

Eine Idee, die ich dafür gemacht habe, ohne Änderungen an Ihrer externen JavaScript-Datei vorzunehmen, ist, den Inhalt der JavaScript-Datei auf AJAXy-Art zu bekommen (und wie Sie das tun) und alles in eine Funktion zu stellen mit der new Function(code) Weise initialisieren dann, dass mit new:

surrogateWindow = new new Function(jsCode)(); 

dann surrogateWindow ist die this dieses Codes. I denke,, dass diese Idee funktionieren sollte.

1

Für den Code, den Sie geschrieben haben, ich glaube, Sie einige der Art und Weise Klassen arbeiten in JavaScript sind Missverständnis. In Java können Sie die this. fallen lassen, aber in JavaScript können Sie nicht. Sie müssen immer this. dort haben. Dann wird Ihr Code:

Es wäre auch gut, es in einer normaleren Klassenweise zu tun. Ich bin mir nicht sicher, was genau Ihre Situation ist, da ich nicht all Ihren Code sehen kann, so dass Sie es vielleicht schon so machen.

function Something(name) { 
    this.name = name; 
} 

var first = new Something("first"); 
var second = new Something("second"); 

document.write('name= '+name+' <br/>\n'); //prints "undefined" 
document.write('first.name= '+first.name+' <br/>\n'); //prints "first" 
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"