html - Hur man undviker namnkonflikter i JavaScript-widgets
Jag har en JavaScript-widget (en bit inbäddad JS- och HTML-kod) som är inbäddad på andra webbplatser. Vad ska jag göra för att säkerställa att dess variabelnamn inte krockar med värdsidans variabler?
Jag skulle vilja att denna widget är "inlined", vilket betyder på samma sida som värdsidan, inte i en iframe. Vad är det bästa sättet att undvika namnkonflikter med värdsidan eller konflikter med andra widgets?
Namnkrockar kan uppstå på flera sätt:
- JavaScript variabelnamn
- JavaScript-funktionsnamn
- DOM-elementidentifierare
- CSS-klassnamn
- kanske mer...
Jag kan tänka mig flera sätt att undvika namnkrockar, men jag undrade om det finns en bästa praxis eller andra allmänna rekommendationer. Så här är mina två cent:
- Använd bara långa och försök-att-vara-unika namn. Det är fult och inte idiotsäkert, men är enkelt i konceptet.
- Använd en iframe. Men som nämnts vill jag inte använda en iframe av flera skäl. Jag vill att widgeten ska ärva stilattribut från sidan (såsom standardteckensnitt och bakgrundsfärg) och viktigast av allt, jag vet inte hur stor widgeten kommer att vara. Det beror på realtidsdata och kan vara i vilken storlek som helst.
- Använd anonyma funktioner för bättre scopning, t.ex. (function(){min kod här})(). Denna lösning, även om den är elegant, fungerar fortfarande inte för mig eftersom för det första löser den bara krockar i JS-namn men inte DOM-ID eller CSS-klasser och för det andra använder jag också JSONP för vilket jag måste tillhandahålla ett callback-funktionsnamn, som i slutändan måste vara i det globala scopet, så det kan inte vara inbäddat i den anonyma funktionens scope.
- Skapa en namespace-mekanism i JavaScript som kommer att ge unikhet för JS-variabler och funktioner. Något i stil med window['my_app'][variable_name] eller window['my_app']function_name. Det är lite fult också, men åtminstone har jag kontroll över namespace och kan generera garanterat unika namespaces.
Svar #1
Javascript-namnrymder:
http://www.codeproject.com/KB/scripting/jsnamespaces.aspx
Det används flitigt i flera JavaScript-ramverk/bibliotek, såsom YUI: http://developer.yahoo.com/yui/yahoo/
Svar #2
I mitt tidigare projekt hade jag en widget som var inbäddad på andra webbplatser, och för att förhindra namnkonflikter prefixade jag alla namn som skulle användas på de inbäddade webbplatserna med ett två-bokstavs prefix (jag fick idén från Objective C, där alla klasser börjar med ett prefix som NS...).
Självklart använde jag också namnrymder (t.ex. var Foo={ bar: function() { ... }}) och "klasser" (med John Resigs klassimplementation), eftersom jag använder dem oavsett om jag har en widget eller inte, men namnen på namnrymderna, klasserna och globala variabler eller funktioner var prefixade - t.ex. HMWidget, HMClass, hmDoSomething(), etc.
När det gäller DOM-ID:n och CSS-klasser - först var jag tvungen att göra mig av med de flesta ID:n på grund av möjligheten att ha flera widgets från min tjänst på samma webbplats. Så de enda ID:n som blev kvar var något i stil med "widget_12345" för att skilja widgets åt. Resten av elementen identifierades med CSS-klasser, och alla CSS-deklarationer gjordes i relation till huvudwidget-behållaren (t.ex. ".my_widget .left_column" istället för bara ".left_column").