Hoe moet ik Javascript-bestanden zelfstandig uitvoeren?

Laten we zeggen dat ik een hele reeks JavaScript-bestandsnamen had:

["funScriptStuff.js", "jQuery.js", "dojo.js", "scriptyScript.js"]

hoe kan ik ze onafhankelijk van elkaar uitvoeren?

Laten we bijvoorbeeld aannemen dat één script een aantal slechte dingen deed, zoals

var undefined = true;
var window = "Windows 98";

en een ander script had code die ervan uitging dat deze globale variabelen niet werden versleuteld

if (a !== undefined) {
  window.open(url);
}

als het eerste script als eerste zou worden uitgevoerd, zou het alles in de tweede beschadigen. Zonder iets in deze scriptbestanden te veranderen, hoe kan ik ze onafhankelijk van elkaar laten werken om te voorkomen dat ze elkaar in de war schoppen?

EDIT: I am not asking what Javascript patterns to use to prevent namespace collisions, like wrapping my code in a big closure and so forth. I know about those. I'm trying to create an environment where you can run arbitrary scripts that I have no control over without them stepping on each other's toes.

1
@PeterOlson niet over het laden van JavaScript-bestanden die iets stoms doen.
toegevoegd de auteur Raynos, de bron
@Pekka Waarom is dat?
toegevoegd de auteur Peter Olson, de bron
Kun je misschien een kopie maken van de globale status en deze opnieuw instellen nadat elk script is uitgevoerd?
toegevoegd de auteur Peter Olson, de bron
Ik denk dat je ze in afzonderlijke documenten op verschillende domeinen moet uitvoeren. Geen andere manier om te voorkomen dat ze met 100% zekerheid in elkaar knoeien
toegevoegd de auteur Pekka 웃, de bron
@ Šime ja, maar dat bedoel ik in essentie: je kunt niet betrouwbaar voorkomen dat een ander script in de context van je document iets (in de globale ruimte) verbreekt voor een ander script. En er is geen goede manier om een ​​dergelijke breuk op te lossen zonder het document opnieuw te laden ... (Als er een is waarvan ik niet weet, zou ik er heel graag over te horen krijgen)
toegevoegd de auteur Pekka 웃, de bron
Maar ze rotzooien elkaar niet, ze verpesten het globale object. Alle scripts die in hetzelfde browservenster worden uitgevoerd, delen hetzelfde globale object.
toegevoegd de auteur Šime Vidas, de bron
Ik vermoed dat dit een pendantieke vraag is. Zo nee, waarom voer je dan zo'n schadelijke code uit? Daar is uw oplossing: voer alleen de code uit die u vertrouwt.
toegevoegd de auteur Thomas Eding, de bron
hoe zit het met itereren op de array en het doen van een document.write() voor elk js-bestand? dat kan werken denk ik.
toegevoegd de auteur aishwarya, de bron

4 antwoord

Voor zover ik weet, kunt u de vervuiling van globale variabelen niet betrouwbaar terugdraaien binnen hetzelfde document.

I think you'll have to run them in separate documents (= <iframe>s) on different domains. No other way to prevent them from messing with each other with 100% certainty.

(Het "verschillende domeinen" -item is om te voorkomen dat echt kwaadaardige code de andere scripts vervuilt (omdat iframes in hetzelfde domein toegang tot elkaar hebben, dus een kwaadaardig script kan op zoek zijn naar andere iframes om een ​​compromis te sluiten .)

3
toegevoegd
<iframe sandbox> is veilig genoeg. .sandbox
toegevoegd de auteur Raynos, de bron
@Pekka werkt niet op verouderde platforms. Het is misschien mogelijk om te emuleren met behulp van caja
toegevoegd de auteur Raynos, de bron
Laten we veronderstellen dat ik op de een of andere manier (ik weet niet zeker hoe) ik een programma had dat de initiële globale status opsloeg en nadat elk script was uitgevoerd, stel het opnieuw in naar wat het eerder was. Zou dat het doel niet juist bereiken?
toegevoegd de auteur Peter Olson, de bron
@Raynos hey, dat is cool! (Alleen HTML5, dus ik neem aan dat het niet werkt in IE <= 8)
toegevoegd de auteur Pekka 웃, de bron
@Peter Ik weet niet zeker of er een manier is om dat te doen dat betrouwbaar werkt en zonder grote problemen in alle browsers. Daar lijkt op dit moment niets van te bestaan, maar misschien weet iemand een suggestie te verzinnen ...
toegevoegd de auteur Pekka 웃, de bron

Definieer alstublieft uw doelomgeving. Binnen de browser en met alleen bestandsnamen is het enige wat u kunt doen, is om elk script met XHR te downloaden, het als stringgegevens te behandelen en eval het (ja, de oplossing is zo onhandig zoals het klinkt). Om rogue script-rommel met je Global scope te voorkomen, moet je de with -instructie gebruiken:

var safeGlobal = {};
safeGlobal.isHoneyPot = true;  //whatever scripts might expect in Global scope
with ( safeGlobal ) {
  eval( scriptText );
}
delete safeGlobal; //purge whatever pollution script leaves in Global scope

De andere benadering binnen de browser is om meerdere vensters of iframes te gebruiken, maar dit maakt de naamruimte niet plat , dus je moet naar functies verwijzen via raam/iframe-variabelen.

2
toegevoegd
@Pekka nee het doet het niet: \ Het moorddadig alle optimalisatie. Ik zou nooit de prestatieboete betalen. Evenmin beschermt het wereldwijde bereik op alle jsfiddle.net/C9uLm
toegevoegd de auteur Raynos, de bron
gebruik nooit met . ooit.
toegevoegd de auteur Raynos, de bron
+1 alleen omdat je erin slaagde om twee "slechte" functies van Javascript in één beknopte hacky-oplossing te passen.
toegevoegd de auteur Peter Olson, de bron
toegevoegd de auteur Pekka 웃, de bron
Hé, dit klinkt interessant! Is het mogelijk om vanuit een met uit te breken? @Raynos ja, maar in dit geval, als het goed is ....?
toegevoegd de auteur Pekka 웃, de bron
@Raynos, wees niet zo dogmatisch :-) Wat denk je dat de browser doet als de scriptbron het laden voltooit? :-)
toegevoegd de auteur OnTheFly, de bron
@Pekka, helaas, nee, het voegt alleen maar enige mate van controle over rogue script van daar.
toegevoegd de auteur OnTheFly, de bron

.js-bestanden zijn slechts blokken JavaScript die op de pagina worden vermeld. Het is niet moeilijk om te documenteren. Schrijf een scripttag in de pagina op basis van de criteria die je hebt. U kunt dus een script hebben dat controleert op een bepaalde voorwaarde en vervolgens het gewenste externe script toevoegt, op basis van die voorwaarde.

Echter, in termen van hun "onafhankelijkheid" heb je een beetje een probleem (wat meestal de primaire critici van Javascript is), dat is dat alles wat je in de pagina gooit, globaal is en zichtbaar voor al het andere. Dit is soms best handig, maar het betekent wel dat je je objecten heel zorgvuldig moet inkapselen om te voorkomen dat ze over elkaar heen bloeden.

Dus als al deze scripts van uzelf zijn, kunt u dit regelen door ervoor te zorgen dat elke set gereedschappen deel uitmaakt van een groter object dat zeer uniek is. Wat betreft het gebruik van frameworks zoals jQuery, moet je gewoon oppassen dat je geen inbreuk maakt op hun objecten. Ze hebben hier echter rekening mee gehouden, dus zolang je weet waar je op moet letten, zou het goed moeten komen.

0
toegevoegd

Ik gebruik vaak dit patroon .

(function(myNamespace, $, undefined) {

    //Public Method
    myNamespace.foo = function() {
       //..
    };

    //Private Method
    function bar() {
       //..
    }
}(window.myNamespace = window.myNamespace || {}, jQuery));

Omdat het derde argument niet is opgegeven, is het zeker undefined .
Als u jQuery gebruikt, zorgt het ervoor dat $ niet op iets anders wordt ingesteld (tenzij natuurlijk jQuery op iets anders is ingesteld).

0
toegevoegd