Come creare uno spazio dei nomi sicuro per la mia applicazione in JavaScript

6

Sto lavorando a un'applicazione nel browser e vorrei assicurarmi che il mio codice non sia in conflitto con il codice di altre librerie o con le possibili chiamate aggiunte dai produttori di browser in futuro.

Nel mio ambiente eviterei le collisioni utilizzando un nome di applicazione univoco e inserendo tutte le mie classi e il codice nel mio dominio in questo modo:

package {
    import com.mydomain.controls.*; // my domain

    public class MyApplication {
        var button:Button = new com.mydomain.Button();
        button.text = "Hello World";
        addChild(button);
    }

}

O quando sto usando un linguaggio dichiarativo definirei il mio URI del namespace e il prefisso in questo modo:

<s:Application xmlns:s="http://www.default.com" xmlns:abc="www.mydomain.com">
   <abc:Button text="Hello world" />
</s:Application>

Ma come faresti nel browser quando stai caricando il codice da diverse librerie? Dove definisco gli oggetti globali e come li rendono unici? Faccio qualcosa di simile:

window["com.mydomain.controls.MyApplication"];

Ho visto le librerie fare qualcosa del tipo:

GalleryWidget = function() { 
      var version = 1.2.3;
      var getGallery = function() { //do stuff };
}

Ma cosa succede se c'è un altro GalleryWidget dove? Scusa se questa è una domanda per principianti.

Addendum
Forse se incollo un codice, questo chiarirà le cose. C'è qualche problema con quanto segue:

window.VideoPlayer = {}; // write my class, etc
window.myVideoPlayer = new VideoPlayer();
window.submitForm = function() {}; //etc
window.parse = function() {}
JSON.parseXML = function(zml) {};
document.write = function() {};

UPDATE 2:
Ho trovato una pagina Web che utilizza gli oggetti globali di Yahoo:

var $D  =  YAHOO.util.Dom;
var $E  =  YAHOO.util.Event;
var $A  =  YAHOO.util.Anim;
var $M  =  YAHOO.util.Motion;
var $EA =  YAHOO.util.Easing;
var $DD =  YAHOO.util.DD;
var $C  =  YAHOO.util.Connect;
var $   =  $D.get;

YAHOO.namespace ("Smb.Asteroids.Logger");
YAHOO.Smb.Asteroids.Logger = {
    Log : function(e) {
        if (typeof console !== 'undefined') {
            console.log(e);
        }
    }
}
var $LOG = YAHOO.Smb.Asteroids.Logger.Log;
    YAHOO.namespace('Smb.Asteroids');
var YSA = YAHOO.Smb.Asteroids;

YSA.Nav = {
    isNavNorth : false,

    init : function() {
        // For the first visit, subscribe to the layout(template) change event
        // When user changes template from the ribbon, we need to re-init this JS, based on the new templates settings. 
        if (YSA.Nav.isFirstVisit) {
            YSA.Nav.isFirstVisit = false;
            if (YSA.UiMgr) {
                YSA.UiMgr.Layout.onChange.eventObj.subscribe(
                    function() { YSA.Nav.init() });
            }
        } else {
            YSA.Nav.clearSubNavStyles();
        }

        YSA.Nav.initNavSettings();
        var navDiv = $('navigation');
        if (! $D.hasClass(navDiv, 'sub_dynamic')) {
            return;
        }
        YSA.Nav.initNavSettings();
        var triggers = $D.getElementsByClassName('trigger', '', navDiv);
        $E.on(triggers, 'mouseover', this.mouseOverTrigger);
        $E.on(triggers, 'mouseout', this.mouseOutTrigger);
        var toggles = $D.getElementsByClassName('toggle', 'a', navDiv);
        $E.on(toggles, 'click', this.toggleClicked);
        var triggers = $D.getElementsByClassName('mainNav', '', navDiv);
        $E.on(triggers, 'mouseover', this.mouseOverMainNav);
    }
};

$E.on(window, 'load', YSA.Nav.init, YSA.Nav, true); 

Ho troncato molto del codice. Si basa sul framework Yahoo YUI qui ma sembra che la pagina non sia disponibile. La macchina di ritorno dovrebbe mostrarlo.

In ogni caso, risponde ad alcune domande che ho avuto. Ma ho notato che questo è basato sul framework 2. Hanno framework 3 che sembra liberarsi dei namespace. In questo modo lascia più domande.

    
posta 1.21 gigawatts 12.01.2017 - 06:36
fonte

2 risposte

1

Dal tuo esempio di codice, sembra che tu non stia creando una libreria JavaScript ma una semplice applicazione.

Per questo, usi inutilmente lo spazio dei nomi finestra . Questo è riservato agli oggetti globali e aggiungendo così tante variabili qui stai cercando solo guai.

In JavaScript, puoi facilmente assicurarti che il tuo codice non sia in conflitto con altre librerie o codice inserendolo in una funzione anonima di autoesecuzione:

(function () {

// Put your code here

})();

Ogni cosa all'interno di questa funzione sarà effettivamente isolata e non dovrai preoccuparti dei nomi delle variabili, ma non usare l'oggetto window per dichiarare una variabile. Quindi il tuo esempio si trasformerebbe in qualcosa di simile a questo:

(function () {

var VideoPlayer = {}; // write my class, etc
var myVideoPlayer = new VideoPlayer();
var submitForm = function() {}; //etc
var parse = function() {}
var parseXML = function(zml) {};
var write = function() {}; 

})();

Se davvero DESIDERA assegnare qualcosa all'oggetto finestra - e lo vuoi solo se stai costruendo una libreria o in rari pochi altri casi - sta a te assicurarti che non ci siano conflitti. Non c'è davvero alcun modo per risolvere questo problema a livello di codice, ma potresti dire all'utente che qualcosa non va:

if (window.myLibrary) {
  throw "Error: you already have a library using myLibrary namespace. Please resolve the conflict."
} else {
  window.myLibrary = function () {} // Get the party started
}

Inoltre, mantieni i nomi creativi e non utilizzati (suggerimento: Google è tuo amico).

    
risposta data 19.01.2017 - 01:08
fonte
0

But what if there is another GalleryWidget some where?

Anche se non puoi mai essere sicuro al 100%, la scelta di uno spazio dei nomi che è improbabile che venga utilizzato da qualcosa ti aiuterà a prevenire questo problema. Il nome ufficiale della tua applicazione normalmente lo farebbe, a meno che non sia molto generico. Quindi GalleryWidget è generico, è improbabile che jquery venga duplicato per qualcosa di diverso da quella libreria.

    
risposta data 12.01.2017 - 10:35
fonte