Il problema con il tentativo di capire in quale ambiente è in esecuzione il tuo codice è che qualsiasi oggetto può essere modificato e dichiarato rendendo quasi impossibile capire quali oggetti sono nativi per l'ambiente e quali sono stati modificati dal programma.
Tuttavia, ci sono alcuni trucchi che possiamo usare per capire con certezza l'ambiente in cui ti trovi.
Iniziamo con la soluzione generalmente accettata utilizzata nella libreria di sottolineatura:
typeof module !== 'undefined' && module.exports
Questa tecnica è in realtà perfettamente valida per il lato server, poiché quando require
viene chiamata la funzione, reimposta l' this
oggetto su un oggetto vuoto e lo ridefinisce module
nuovamente per te, il che significa che non devi preoccuparti di manomissioni esterne. Finché il tuo codice è caricato require
, sei al sicuro.
Tuttavia, questo cade a pezzi sul browser, poiché chiunque può facilmente definirlo module
per far sembrare che sia l'oggetto che stai cercando. Da un lato questo potrebbe essere il comportamento desiderato, ma determina anche quali variabili l'utente della libreria può utilizzare nell'ambito globale. Forse qualcuno vuole usare una variabile con il nome module
che ha exports
al suo interno per un altro uso. È improbabile, ma chi siamo noi per giudicare quali variabili qualcun altro può usare, solo perché un altro ambiente utilizza quel nome di variabile?
Il trucco, tuttavia, è che se stiamo assumendo che il tuo script sia caricato nell'ambito globale (che sarà se viene caricato tramite un tag di script) una variabile non può essere riservata in una chiusura esterna, perché il browser non lo consente . Ora ricorda nel nodo, l' this
oggetto è un oggetto vuoto, eppure la module
variabile è ancora disponibile. Questo perché è dichiarato in una chiusura esterna. Quindi possiamo quindi correggere il controllo di sottolineatura aggiungendo un controllo extra:
this.module !== module
Con questo, se qualcuno dichiara module
nell'ambito globale nel browser, verrà inserito this
nell'oggetto, il che provocherà il fallimento del test, poiché this.module
sarà lo stesso oggetto del modulo. Sul nodo, this.module
non esiste ed module
esiste all'interno di una chiusura esterna, quindi il test avrà esito positivo, poiché non sono equivalenti.
Pertanto, il test finale è:
typeof module !== 'undefined' && this.module !== module
Nota: sebbene ciò ora consenta alla module
variabile di essere utilizzata liberamente nell'ambito globale, è comunque possibile aggirarla nel browser creando una nuova chiusura e dichiarando al suo module
interno, quindi caricando lo script all'interno di quella chiusura. A quel punto l'utente sta replicando completamente l'ambiente del nodo e, si spera, sa cosa sta facendo e sta cercando di fare uno stile di nodo richiesto. Se il codice viene chiamato in un tag script, sarà comunque al sicuro da eventuali nuove chiusure esterne.