Ci sono costanti in JavaScript?


1132

C'è un modo per usare le costanti in JavaScript ?

In caso contrario, qual è la pratica comune per specificare le variabili utilizzate come costanti?


35
Chrometi permette di usare la parola chiave constper usare le costanti. es const ASDF = "asdf". Tuttavia, poiché constnon è compatibile con più browser, di solito mi attengo a una vardichiarazione.
Jacksonkr,

20
try{const thing=1091;}catch(e){var thing=1091;}lavori.
Derek 功夫 會 功夫

13
Derek: il tuo tentativo / cattura non limiterebbe l'ambito della cosa che stai dichiarando al blocco try / catch? Se non si esegue correttamente l'ambito, qual è il punto di specificare consto varaffatto?
Coderer

8
@Coderer nelle attuali implementazioni, questo funzionerà, poiché constha lo stesso ambito di applicazione var, ed è a livello di funzione, non a livello di blocco. Se segui invece lo standard ECMAScript imminente, constha lo stesso ambito di let, il che significa che non funzionerà.
Jasper,

3
@Coderer Linguaggio sbagliato. Le variabili in JavaScript sono l'ambito della funzione. Questo non è C.
doug65536,

Risposte:


1018

Da ES2015 , JavaScript ha una nozione di const:

const MY_CONSTANT = "some-value";

Funzionerà praticamente in tutti i browser tranne IE 8, 9 e 10 . Alcuni potrebbero anche aver bisogno della modalità rigorosa abilitata.

È possibile utilizzare varcon convenzioni come ALL_CAPS per mostrare che determinati valori non devono essere modificati se è necessario supportare browser più vecchi o si lavora con codice legacy:

var MY_CONSTANT = "some-value";

60
Che ne dici di const x = 24;
Zachary Scott,

93
Nota che se non hai bisogno di compatibilità cross-browser (o se stai programmando sul lato server in Rhino o Node.js) puoi usare la constparola chiave. Attualmente è supportato da tutti i browser moderni ad eccezione di IE.
Husky,

17
In questi giorni (3,5 anni dopo) è possibile utilizzare Object.definePropertyper creare proprietà di sola lettura che non possono essere eliminate. Funziona nella versione corrente di tutti i principali browser (ma in modo errato in IE8 ). Vedi la risposta di @NotAName
Phrogz,

12
@Amyth Non è molto utile. È una guida di stile proposta da un unico venditore. Come indicato sopra dal punto Husky, la compatibilità con IE è totalmente irrilevante quando si scrive JS lato server.
Annunciato il

32
Poiché questa risposta è ancora ampiamente classificata da Google nel 2015, si dovrebbe dire che ora è obsoleta. La constparola chiave è ora ufficialmente parte della lingua ed è supportata da ogni browser. Secondo statcounter.com solo un po 'del percento degli utenti di Internet utilizza ancora vecchie versioni del browser che non supportavano const.
tristan,

310

Stai cercando di proteggere le variabili dalle modifiche? In tal caso, è possibile utilizzare un modello di modulo:

var CONFIG = (function() {
     var private = {
         'MY_CONST': '1',
         'ANOTHER_CONST': '2'
     };

     return {
        get: function(name) { return private[name]; }
    };
})();

alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

CONFIG.MY_CONST = '2';
alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

CONFIG.private.MY_CONST = '2';                 // error
alert('MY_CONST: ' + CONFIG.get('MY_CONST'));  // 1

Utilizzando questo approccio, i valori non possono essere modificati. Ma devi usare il metodo get () su CONFIG :(.

Se non è necessario proteggere rigorosamente il valore delle variabili, fare semplicemente come suggerito e utilizzare una convenzione di TUTTI MAIUSCOLI.


13
Nota che potresti semplicemente restituire una funzione per il valore di CONFIG. Ciò ti salverebbe chiamando CONFIG.get () sempre.
Mathew Byrne,

4
Bella soluzione. Ma tali cose dovrebbero essere racchiuse in una biblioteca per non reinventarle in nessun nuovo progetto.
andrii

82
CONFIG.get = someNewFunctionThatBreaksTheCode... Tutto sommato, non è assolutamente possibile applicare costanti in JS (senza parola chiave const). L'unica cosa che puoi fare è limitare la visibilità.
Thomas Eding,

28
Credo che privatesia una parola riservata futura in JavaScript, non lo userei se fossi in te.
Zaq,

Questo è anche il modello di registro.

122

La constparola chiave è nella bozza di ECMAScript 6 ma finora gode solo di un'infarinatura del supporto del browser: http://kangax.github.io/compat-table/es6/ . La sintassi è:

const CONSTANT_NAME = 0;

13
Se si tenta di assegnare un valore a const, non vengono generati errori. L'assegnazione fallisce e la costante ha ancora il suo valore originale. Questo è un grosso difetto di progettazione IMHO, ma finché ci sarà una convenzione di denominazione chiara e coerente (come il popolare ALL_CAPS), non penso che causerebbe troppo dolore.
MatrixFrog,

6
Tieni d'occhio il supporto del browser qui: kangax.github.io/es5-compat-table/es6/#const
Mark McDonald

6
L'assegnazione @MatrixFrog genererà un errore con 'use strict'.
sam

Devo definire le costanti in ALL CAPS?
Lewis,

1
@Tresdin È una convenzione di denominazione comune definire le costanti in tutte le maiuscole. Nulla nelle specifiche del linguaggio lo costringe, ma non è una cattiva idea. Rende più chiaro quale sia la tua intenzione, quindi migliora la leggibilità del codice.
Bill the Lizard,

68
"use strict";

var constants = Object.freeze({
    "π": 3.141592653589793 ,
    "e": 2.718281828459045 ,
    "i": Math.sqrt(-1)
});

constants.π;        // -> 3.141592653589793
constants = 3;    // -> TypeError: Cannot assign to read only property 'π' …
constants.π;        // -> 3.141592653589793

delete constants.π; // -> TypeError: Unable to delete property.
constants.π;        // -> 3.141592653589793

Vedi Object.freeze . È possibile utilizzare ancheconst se si desidera rendere il constantsriferimento di sola lettura.


2
Dovrei menzionarlo, funziona solo su IE9 + kangax.github.io/compat-table/es5 .
Cordle,

Se non avesse avuto l'implementazione non i
corretta

Nota: ciò si comporta in modo simile alla constdichiarazione ES6 , ad es. Le proprietà non possono essere dichiarate o riassegnate, ma se sono di tipo dati object, possono essere mutate.
le_m,

Esattamente quello che stavo cercando. Puoi anche usare const constantsinvece di var constantsper impedire che la variabile venga riassegnata.
Jarett Millard,

Vedi, ad esempio, surgelati per il congelamento ricorsiva.
sam,

64

IE supporta costanti, una sorta di, ad esempio:

<script language="VBScript">
 Const IE_CONST = True
</script>
<script type="text/javascript">
 if (typeof TEST_CONST == 'undefined') {
    const IE_CONST = false;
 }
 alert(IE_CONST);
</script>

50
Ragazzo, parla di qualcosa che non è cross-browser. . . Ancora +1 per pensare un po 'fuori dagli schemi.
Tom,

14
VBScript? Cos'è quello? ;)
tybro0103,

2
Di solito voto in basso per una domanda generale relativa a più browser, con una risposta specifica di IE. Perché odio le persone che pensano che l'implementazione javascript di IE sia "The One", e che gli altri debbano essere ignorati. Chi usa altri debitori diversi da IE, a proposito?
Formica

@Cooluhuru questo script sembra gestire sia i browser IE (usando VBScript) sia i browser non IE (usando JavaScript const). Puoi spiegarci cosa c'è che non va?
Andrew Grimm,

Ho ancora difficoltà ad accettare che le costanti possano essere cambiate.
Norbert Norbertson,

59

ECMAScript 5 introduce Object.defineProperty:

Object.defineProperty (window,'CONSTANT',{ value : 5, writable: false });

È supportato in tutti i browser moderni (così come IE ≥ 9).

Vedi anche: Object.defineProperty in ES5?


1
Vale la pena notare che questo non è come una costante tradizionale. Ciò consentirà solo di definire una proprietà costante (di un oggetto non costante). Inoltre, questo non genera un errore e restituisce anche il valore che si tenta di impostare. Semplicemente non scrive il valore.
Cory Gross,

3
Di recente ho letto che tentare di assegnare a una proprietà con writable: false genererà effettivamente un errore se il codice che esegue l'assegnazione viene interpretato in modalità rigorosa di ECMAScript 5. Solo un altro motivo per scrivere 'use strict'nel tuo codice.
Cory Gross,

6
Puoi effettivamente omettere writable: falsepoiché è l' impostazione predefinita .
sam,

24

No, non in generale. Firefox implementa constma so che IE no.


@John indica una pratica di denominazione comune per i consensi che è stata usata per anni in altre lingue, non vedo alcun motivo per cui non sia possibile utilizzarla. Ovviamente ciò non significa che qualcuno non scriverà comunque sul valore della variabile. :)


11
Come tutti sanno, se IE non lo implementa, potrebbe anche non esistere.
Josh Hinman,

3
Sfortunatamente, e praticamente parlando - è vero. IE possiede un'enorme quota di mercato. Se possedessi un'azienda e avessi applicazioni web utilizzate internamente, standardizzerei FF. Non so perché così tante persone si preoccupino di IE, che soffia.
Jason Bunting,

@Rich: chi ha detto che la mia opinione era reale? Hai fatto abbastanza il presupposto. Inoltre, per quanto mi riguarda, il fatto che IE faccia schifo è un dato di fatto. Puoi avere i tuoi fatti, non ho detto che dovevi credere ai miei. : P Prendi uno Xanax o qualcosa del genere ...
Jason Bunting,

@Rich B, sì, era solo un commento stupido da fare, e fidati di me, lo saprei, faccio molti commenti stupidi. @Jason B. - interessante, ho incontrato questo problema ieri sera .. const ha funzionato in FF ma non in IE. Grazie per il chiarimento

A chi importa di IE? Io non! FF o Chrome o Opera ecc ... possono essere installati quasi in ogni piattaforma del sistema operativo. Anche i rivenditori di computer di solito sanno che la vecchia versione di IE fa schifo, quindi spesso (o anche ogni volta) installano browser alternativi prima di vendere un computer. Quindi ho deciso che la mia app sviluppata non si preoccupasse affatto di browser incompatibili: se gli sviluppatori di browser si preoccupano di rispettare gli standard il loro prodotto può usare la mia app, in caso contrario, gli utenti useranno un browser diverso ... Posso conviverci; -) Ma Microsoft può vivere perdendo parte del mercato? No, non possono così "Loro" cambieranno la loro politica di sviluppo!
Wilson Winka,

20

In JavaScript, la mia preferenza è quella di utilizzare le funzioni per restituire valori costanti.

function MY_CONSTANT() {
   return "some-value";
}


alert(MY_CONSTANT());

6
Vale la pena sottolineare che questo rientra nello stesso problema menzionato nella risposta di @Burkes (commento di @trinithis). `MY_CONSTANT = function () {return" some-other-value "; } lo rompe. +1 però, soluzione decente e veloce.
Patrick M,

13
-1. Questo non ha alcun vantaggio rispetto a var SOME_NAME = value (è ancora modificabile), è più codice e richiede spiegazioni.
mikemaccana,

@PatrickM mentre è vero che puoi modificare quel tipo di pseudo-costanti, in altre lingue come ad esempio C, su cui non dovresti essere in grado di modificare le costanti, puoi comunque farlo tramite ad esempio puntatori. Quindi, finché usi un approccio che almeno suggerisce che è una costante, va bene anche.
rev

20

Mozillas MDN Web Docs contiene buoni esempi e spiegazioni su const. Estratto:

// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;

// this will throw an error - Uncaught TypeError: Assignment to constant variable.
MY_FAV = 20;

Ma è triste che IE9 / 10 non supporti ancora const. E il motivo è assurdo :

Quindi, cosa sta facendo IE9 con const? Finora, la nostra decisione è stata quella di non supportarlo. Non è ancora una funzionalità di consenso in quanto non è mai stata disponibile su tutti i browser.

...

Alla fine, sembra che la migliore soluzione a lungo termine per il web sia lasciarla fuori e aspettare che i processi di standardizzazione seguano il loro corso.

Non lo implementano perché altri browser non lo hanno implementato correttamente ?! Hai paura di renderlo migliore? Definizioni standard o no, una costante è una costante: impostata una volta, mai modificata.

E a tutte le idee: ogni funzione può essere sovrascritta (XSS ecc.). Quindi non vi è alcuna differenza in varo function(){return}. constè l'unica vera costante.

Aggiornamento: IE11 supporta const :

IE11 include il supporto per le caratteristiche ben definite e comunemente usati emergente ECMAScript 6 serie come let, const, Map, Set, e WeakMap, così come __proto__per migliorare l'interoperabilità.


25
"non è mai stato disponibile su tutti i browser". Se non lo rendi disponibile in Internet Explorer, non sarà mai presente in tutti i browser.
km1,

guidare la standardizzazione non è per tutti;) - le aziende vanno e vengono di nuovo - grazie per aver citato le probabilità nel bosco
Quicker

ancora uno su questo: VBA non è ancora una funzionalità di consesus in tutti i browser e MS supporta const in VBA - questa è la padronanza della canalizzazione dei budget di sviluppo;)
Quicker

17

Se non ti dispiace usare le funzioni:

var constant = function(val) {
   return function() {
        return val;
    }
}

Questo approccio offre funzioni anziché variabili regolari, ma garantisce * che nessuno può modificare il valore una volta impostato.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Personalmente lo trovo piuttosto piacevole, specialmente dopo essermi abituato a questo modello da osservabili knockout.

* A meno che qualcuno non abbia ridefinito la funzione constantprima di averla chiamata


1
underscore.js implementa una funzione costante identica a questo codice.
Upperstage,

Semplice, conciso e risponde allo spirito della domanda di OP. Ciò avrebbe dovuto ricevere più voti positivi.
Mac,

3
Questo non ha mai funzionato davvero per me. Anche se la chiusura lo rende immutabile, il var a cui lo assegni può essere comunque sovrascritto. Es: a = constant(10); a(10); // 10seguito da a = constant(25); a(); //25, nessun errore o avviso dato, nessuna indicazione che la tua costante è stata rotta.
Patrick M,

Se riassegno il valore a, aallora cambia in un nuovo valore
Saurabh Sharma,

17

con il "nuovo" oggetto API puoi fare qualcosa del genere:

var obj = {};
Object.defineProperty(obj, 'CONSTANT', {
  configurable: false
  enumerable: true,
  writable: false,
  value: "your constant value"
});

dai un'occhiata a questo su MDN Mozilla per maggiori dettagli. Non è una variabile di primo livello, poiché è collegata a un oggetto, ma se si dispone di un ambito, qualsiasi cosa, è possibile collegarlo a quello. thisdovrebbe funzionare anche. Quindi, ad esempio, farlo nell'ambito globale dichiarerà un valore pseudo costante sulla finestra (il che è una pessima idea, non dovresti dichiarare negativamente i varchi globali)

Object.defineProperty(this, 'constant', {
  enumerable: true, 
  writable: false, 
  value: 7, 
  configurable: false
});

> constant
=> 7
> constant = 5
=> 7

nota: l'assegnazione restituirà il valore assegnato nella console, ma il valore della variabile non cambierà


Non funziona in Safari e in Mozilla se si esegue di nuovo l'istruzione define - con un valore diverso - riassegnerà il valore.
Akshay,

2
Non "non funziona in Safari", non supportato in Safari. Non lo stesso. E dovrebbe lanciare un 'Uncaught TypeError: Impossibile ridefinire la proprietà: <nome proprietà qui>' se lo provi. o stai sbagliando o il tuo ff lo ha implementato in modo errato. Immagino sia un mix di entrambi.
Tenshou,

14

Raggruppa le costanti in strutture ove possibile:

Esempio, nel mio attuale progetto di gioco, ho usato di seguito:

var CONST_WILD_TYPES = {
    REGULAR: 'REGULAR',
    EXPANDING: 'EXPANDING',
    STICKY: 'STICKY',
    SHIFTING: 'SHIFTING'
};

Incarico:

var wildType = CONST_WILD_TYPES.REGULAR;

confronto:

if (wildType === CONST_WILD_TYPES.REGULAR) {
    // do something here
}

Più recentemente sto usando, per confronto:

switch (wildType) {
    case CONST_WILD_TYPES.REGULAR:
        // do something here
        break;
    case CONST_WILD_TYPES.EXPANDING:
        // do something here
        break;
}

IE11 è con il nuovo standard ES6 che ha una dichiarazione 'const'.
Sopra funziona nei browser precedenti come IE8, IE9 e IE10.


12

Puoi facilmente dotare il tuo script di un meccanismo per le costanti che possono essere impostate ma non modificate. Un tentativo di modificarli genererà un errore.

/* author Keith Evetts 2009 License: LGPL  
anonymous function sets up:  
global function SETCONST (String name, mixed value)  
global function CONST (String name)  
constants once set may not be altered - console error is generated  
they are retrieved as CONST(name)  
the object holding the constants is private and cannot be accessed from the outer script directly, only through the setter and getter provided  
*/

(function(){  
  var constants = {};  
  self.SETCONST = function(name,value) {  
      if (typeof name !== 'string') { throw new Error('constant name is not a string'); }  
      if (!value) { throw new Error(' no value supplied for constant ' + name); }  
      else if ((name in constants) ) { throw new Error('constant ' + name + ' is already defined'); }   
      else {   
          constants[name] = value;   
          return true;  
    }    
  };  
  self.CONST = function(name) {  
      if (typeof name !== 'string') { throw new Error('constant name is not a string'); }  
      if ( name in constants ) { return constants[name]; }    
      else { throw new Error('constant ' + name + ' has not been defined'); }  
  };  
}())  


// -------------  demo ----------------------------  
SETCONST( 'VAT', 0.175 );  
alert( CONST('VAT') );


//try to alter the value of VAT  
try{  
  SETCONST( 'VAT', 0.22 );  
} catch ( exc )  {  
   alert (exc.message);  
}  
//check old value of VAT remains  
alert( CONST('VAT') );  


// try to get at constants object directly  
constants['DODO'] = "dead bird";  // error  

12

Dimentica IE e usa la constparola chiave.


9
per me va bene! ma poi sto scrivendo un'estensione di Chrome, quindi so di essere su un browser sano ...
yoyo

1
La parte migliore di @yoyo sulla scrittura di estensioni e componenti aggiuntivi - nessun supporto cross-browser!
Ian,

1
@Ian Benvenuti nel 2019, l'incoerenza tra browser è quasi scomparsa :)
Fusseldieb,

9

Eppure non esiste un modo predefinito cross-browser esatto per farlo, puoi ottenerlo controllando l'ambito delle variabili come mostrato in altre risposte.

Ma suggerirò di usare lo spazio dei nomi per distinguere dalle altre variabili. questo ridurrà al minimo le possibilità di collisione da altre variabili.

Proprio come lo spazio dei nomi

var iw_constant={
     name:'sudhanshu',
     age:'23'
     //all varibale come like this
}

quindi durante l'utilizzo sarà iw_constant.nameoiw_constant.age

Puoi anche bloccare l'aggiunta di qualsiasi nuova chiave o la modifica di qualsiasi chiave all'interno di iw_constant utilizzando il metodo Object.freeze. Tuttavia, non è supportato sul browser legacy.

ex:

Object.freeze(iw_constant);

Per i browser meno recenti è possibile utilizzare polyfill per il metodo di blocco.


Se sei d'accordo con la funzione di chiamata, il modo migliore per definire la costante è il seguente browser incrociato. Scoping del tuo oggetto all'interno di una funzione di auto-esecuzione e restituzione di una funzione get per le tue costanti es:

var iw_constant= (function(){
       var allConstant={
             name:'sudhanshu',
             age:'23'
             //all varibale come like this

       };

       return function(key){
          allConstant[key];
       }
    };

// per ottenere il valore usa iw_constant('name')oiw_constant('age')


** In entrambi gli esempi devi stare molto attento alla spaziatura dei nomi in modo che l'oggetto o la funzione non vengano sostituiti con un'altra libreria (se l'oggetto o la funzione stessa verranno sostituiti, l'intera costante andrà)


7

Per un po ', ho specificato "costanti" (che in realtà non erano ancora costanti) nei letterali degli oggetti passati alle with()istruzioni. Ho pensato che fosse così intelligente. Ecco un esempio:

with ({
    MY_CONST : 'some really important value'
}) {
    alert(MY_CONST);
}

In passato, ho anche creato uno CONSTspazio dei nomi in cui avrei inserito tutte le mie costanti. Ancora una volta, con il sovraccarico. Sheesh.

Ora, lo faccio solo var MY_CONST = 'whatever';per KISS .


16
Se c'è qualcosa di più malvagio di Eval, lo è sicuramente with.
NikiC

4
eval è molto malvagio! Una volta ha bruciato la mia casa!
W3Geek,

6

La mia opinione (funziona solo con oggetti).

var constants = (function(){
  var a = 9;

  //GLOBAL CONSTANT (through "return")
  window.__defineGetter__("GCONST", function(){
    return a;
  });

  //LOCAL CONSTANT
  return {
    get CONST(){
      return a;
    }
  }
})();

constants.CONST = 8; //9
alert(constants.CONST); //9

Provare! Ma comprendi: questo è un oggetto, ma non una semplice variabile.

Prova anche solo:

const a = 9;

5

Anch'io ho avuto un problema con questo. E dopo un po 'cercare la risposta e guardare tutte le risposte di tutti, penso di aver trovato una soluzione praticabile a questo.

Sembra che la maggior parte delle risposte che ho incontrato stia usando le funzioni per contenere le costanti. Come molti degli utenti dei MOLTI forum pubblicano, le funzioni possono essere facilmente sovrascritte dagli utenti sul lato client. Sono stato incuriosito dalla risposta di Keith Evetts secondo cui l'oggetto delle costanti non è accessibile dall'esterno, ma solo dalle funzioni all'interno.

Quindi ho trovato questa soluzione:

Metti tutto all'interno di una funzione anonima in modo che le variabili, gli oggetti, ecc. Non possano essere modificati dal lato client. Inoltre, nascondi le funzioni "reali" facendo in modo che altre funzioni chiamino le funzioni "reali" dall'interno. Ho anche pensato di utilizzare le funzioni per verificare se una funzione è stata modificata da un utente sul lato client. Se le funzioni sono state modificate, cambiarle di nuovo usando le variabili 'protette' all'interno e che non possono essere modificate.

/*Tested in: IE 9.0.8; Firefox 14.0.1; Chrome 20.0.1180.60 m; Not Tested in Safari*/

(function(){
  /*The two functions _define and _access are from Keith Evetts 2009 License: LGPL (SETCONST and CONST).
    They're the same just as he did them, the only things I changed are the variable names and the text
    of the error messages.
  */

  //object literal to hold the constants
  var j = {};

  /*Global function _define(String h, mixed m). I named it define to mimic the way PHP 'defines' constants.
    The argument 'h' is the name of the const and has to be a string, 'm' is the value of the const and has
    to exist. If there is already a property with the same name in the object holder, then we throw an error.
    If not, we add the property and set the value to it. This is a 'hidden' function and the user doesn't
    see any of your coding call this function. You call the _makeDef() in your code and that function calls
    this function.    -    You can change the error messages to whatever you want them to say.
  */
  self._define = function(h,m) {
      if (typeof h !== 'string') { throw new Error('I don\'t know what to do.'); }
      if (!m) { throw new Error('I don\'t know what to do.'); }
      else if ((h in j) ) { throw new Error('We have a problem!'); }
      else {
          j[h] = m;
          return true;
    }
  };

  /*Global function _makeDef(String t, mixed y). I named it makeDef because we 'make the define' with this
    function. The argument 't' is the name of the const and doesn't need to be all caps because I set it
    to upper case within the function, 'y' is the value of the value of the const and has to exist. I
    make different variables to make it harder for a user to figure out whats going on. We then call the
    _define function with the two new variables. You call this function in your code to set the constant.
    You can change the error message to whatever you want it to say.
  */
  self._makeDef = function(t, y) {
      if(!y) { throw new Error('I don\'t know what to do.'); return false; }
      q = t.toUpperCase();
      w = y;
      _define(q, w);
  };

  /*Global function _getDef(String s). I named it getDef because we 'get the define' with this function. The
    argument 's' is the name of the const and doesn't need to be all capse because I set it to upper case
    within the function. I make a different variable to make it harder for a user to figure out whats going
    on. The function returns the _access function call. I pass the new variable and the original string
    along to the _access function. I do this because if a user is trying to get the value of something, if
    there is an error the argument doesn't get displayed with upper case in the error message. You call this
    function in your code to get the constant.
  */
  self._getDef = function(s) {
      z = s.toUpperCase();
      return _access(z, s);
  };

  /*Global function _access(String g, String f). I named it access because we 'access' the constant through
    this function. The argument 'g' is the name of the const and its all upper case, 'f' is also the name
    of the const, but its the original string that was passed to the _getDef() function. If there is an
    error, the original string, 'f', is displayed. This makes it harder for a user to figure out how the
    constants are being stored. If there is a property with the same name in the object holder, we return
    the constant value. If not, we check if the 'f' variable exists, if not, set it to the value of 'g' and
    throw an error. This is a 'hidden' function and the user doesn't see any of your coding call this
    function. You call the _getDef() function in your code and that function calls this function.
    You can change the error messages to whatever you want them to say.
  */
  self._access = function(g, f) {
      if (typeof g !== 'string') { throw new Error('I don\'t know what to do.'); }
      if ( g in j ) { return j[g]; }
      else { if(!f) { f = g; } throw new Error('I don\'t know what to do. I have no idea what \''+f+'\' is.'); }
  };

  /*The four variables below are private and cannot be accessed from the outside script except for the
    functions inside this anonymous function. These variables are strings of the four above functions and
    will be used by the all-dreaded eval() function to set them back to their original if any of them should
    be changed by a user trying to hack your code.
  */
  var _define_func_string = "function(h,m) {"+"      if (typeof h !== 'string') { throw new Error('I don\\'t know what to do.'); }"+"      if (!m) { throw new Error('I don\\'t know what to do.'); }"+"      else if ((h in j) ) { throw new Error('We have a problem!'); }"+"      else {"+"          j[h] = m;"+"          return true;"+"    }"+"  }";
  var _makeDef_func_string = "function(t, y) {"+"      if(!y) { throw new Error('I don\\'t know what to do.'); return false; }"+"      q = t.toUpperCase();"+"      w = y;"+"      _define(q, w);"+"  }";
  var _getDef_func_string = "function(s) {"+"      z = s.toUpperCase();"+"      return _access(z, s);"+"  }";
  var _access_func_string = "function(g, f) {"+"      if (typeof g !== 'string') { throw new Error('I don\\'t know what to do.'); }"+"      if ( g in j ) { return j[g]; }"+"      else { if(!f) { f = g; } throw new Error('I don\\'t know what to do. I have no idea what \\''+f+'\\' is.'); }"+"  }";

  /*Global function _doFunctionCheck(String u). I named it doFunctionCheck because we're 'checking the functions'
    The argument 'u' is the name of any of the four above function names you want to check. This function will
    check if a specific line of code is inside a given function. If it is, then we do nothing, if not, then
    we use the eval() function to set the function back to its original coding using the function string
    variables above. This function will also throw an error depending upon the doError variable being set to true
    This is a 'hidden' function and the user doesn't see any of your coding call this function. You call the
    doCodeCheck() function and that function calls this function.    -    You can change the error messages to
    whatever you want them to say.
  */
  self._doFunctionCheck = function(u) {
      var errMsg = 'We have a BIG problem! You\'ve changed my code.';
      var doError = true;
      d = u;
      switch(d.toLowerCase())
      {
           case "_getdef":
               if(_getDef.toString().indexOf("z = s.toUpperCase();") != -1) { /*do nothing*/ }
               else { eval("_getDef = "+_getDef_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_makedef":
               if(_makeDef.toString().indexOf("q = t.toUpperCase();") != -1) { /*do nothing*/ }
               else { eval("_makeDef = "+_makeDef_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_define":
               if(_define.toString().indexOf("else if((h in j) ) {") != -1) { /*do nothing*/ }
               else { eval("_define = "+_define_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           case "_access":
               if(_access.toString().indexOf("else { if(!f) { f = g; }") != -1) { /*do nothing*/ }
               else { eval("_access = "+_access_func_string); if(doError === true) { throw new Error(errMsg); } }
               break;
           default:
                if(doError === true) { throw new Error('I don\'t know what to do.'); }
      }
  };

  /*Global function _doCodeCheck(String v). I named it doCodeCheck because we're 'doing a code check'. The argument
    'v' is the name of one of the first four functions in this script that you want to check. I make a different
    variable to make it harder for a user to figure out whats going on. You call this function in your code to check
    if any of the functions has been changed by the user.
  */
  self._doCodeCheck = function(v) {
      l = v;
      _doFunctionCheck(l);
  };
}())

Sembra anche che la sicurezza sia davvero un problema e non c'è modo di "nascondere" la programmazione dal lato client. Una buona idea per me è comprimere il codice in modo che sia davvero difficile per chiunque, incluso te, il programmatore, leggerlo e comprenderlo. È possibile visitare un sito: http://javascriptcompressor.com/ . (Questo non è il mio sito, non ti preoccupare, non sto facendo pubblicità.) Questo è un sito che ti permetterà di comprimere e offuscare il codice Javascript gratuitamente.

  1. Copia tutto il codice nello script sopra e incollalo nella textarea superiore nella pagina javascriptcompressor.com.
  2. Selezionare la casella di controllo Codifica Base62, selezionare la casella di controllo Riduci variabili.
  3. Premi il pulsante Comprimi.
  4. Incolla e salva tutto in un file .js e aggiungilo alla tua pagina in testa alla tua pagina.

Questa è una buona soluzione che potrebbe essere facilmente racchiusa in una libreria da includere. Ma non mi piace la denominazione delle variabili in questo codice. Perché eliminare i nomi descrittivi come "nome" e "valore" come usati nel codice di Keith? Problema minore, ma comunque.
Cordle,

5

Chiaramente questo dimostra la necessità di una parola chiave const standardizzata per più browser.

Ma per ora:

var myconst = value;

o

Object['myconst'] = value;

Entrambi sembrano sufficienti e qualsiasi altra cosa è come sparare a una mosca con un bazooka.


prendi il buon vecchio var myconst = value; e per il debug utilizzare un codice di debug aggiuntivo ... - funziona come un matto fintanto che non tutti i browser supportano const
Quicker

4

Uso constinvece i varmiei script Greasemonkey, ma è perché verranno eseguiti solo su Firefox ... Anche la
convenzione dei nomi può davvero essere la strada da percorrere (faccio entrambi!).


4

In JavaScript la mia pratica è stata quella di evitare le costanti il ​​più possibile e utilizzare invece le stringhe. I problemi con le costanti compaiono quando vuoi esporre le tue costanti al mondo esterno:

Ad esempio, è possibile implementare la seguente API Data:

date.add(5, MyModule.Date.DAY).add(12, MyModule.Date.HOUR)

Ma è molto più breve e naturale scrivere semplicemente:

date.add(5, "days").add(12, "hours")

In questo modo "giorni" e "ore" si comportano davvero come costanti, perché non puoi cambiare dall'esterno quanti secondi "ore" rappresentano. Ma è facile da sovrascrivere MyModule.Date.HOUR.

Questo tipo di approccio aiuterà anche nel debug. Se Firebug ti dice che action === 18è abbastanza difficile capire cosa significhi, ma quando lo vedi action === "save"è immediatamente chiaro.


Sfortunatamente è abbastanza facile commettere errori di ortografia - ad esempio "Hours"invece di "hours"- ma un IDE potrebbe farti sapere all'inizio che Date.Hoursnon è definito.
le_m,

4

Va bene, è brutto, ma mi dà una costante in Firefox e Chromium, una costante incostante (WTF?) In Safari e Opera e una variabile in IE.

Ovviamente eval () è malvagio, ma senza di esso, IE genera un errore, impedendo l'esecuzione degli script.

Safari e Opera supportano la parola chiave const, ma puoi modificare il valore della const .

In questo esempio, il codice lato server sta scrivendo JavaScript nella pagina, sostituendo {0} con un valore.

try{
    // i can haz const?
    eval("const FOO='{0}';");
    // for reals?
    var original=FOO;
    try{
        FOO='?NO!';
    }catch(err1){
        // no err from Firefox/Chrome - fails silently
        alert('err1 '+err1);
    }
    alert('const '+FOO);
    if(FOO=='?NO!'){
        // changed in Sf/Op - set back to original value
        FOO=original;
    }
}catch(err2){
    // IE fail
    alert('err2 '+err2);
    // set var (no var keyword - Chrome/Firefox complain about redefining const)
    FOO='{0}';
    alert('var '+FOO);
}
alert('FOO '+FOO);

A cosa serve questo? Non molto, dal momento che non è cross-browser. Nel migliore dei casi, forse un po 'di tranquillità che almeno alcuni browser non consentiranno ai bookmarklet o agli script di terze parti di modificare il valore.

Testato con Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9.


1
Adoro quel codice! Brutto come diamine, ma un buon test per il supporto const. =)
Stein G. Strindhaug,

1
un po 'divertente, ehm - quante righe puoi scrivere per dichiarare una const?
Più veloce il

4

Se vale la pena menzionare, è possibile definire costanti in angolare usando$provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');

... e puoi usare const in VBA ... xbrowser? ... ups ...;)
veloce

OP chiede informazioni su javascript, la risposta si occupa di un framework JS altamente ponderato specifico. Praticamente fuori tema.
rimbalzo

2
@rounce: off-topic risposte sono ancora risposte, non la bandiera loro come non è una risposta , ma downvote e voto da eliminare , invece. Vedi Come posso usare correttamente il flag “Not an Answer”?
Kevin Guan,

@KevinGuan Notato, lo farà in futuro.
rimbalzo

4

Una versione migliorata della risposta di Burke che ti consente di fare CONFIG.MY_CONSTinvece di CONFIG.get('MY_CONST').

Richiede IE9 + o un browser Web reale.

var CONFIG = (function() {
    var constants = {
        'MY_CONST': 1,
        'ANOTHER_CONST': 2
    };

    var result = {};
    for (var n in constants)
        if (constants.hasOwnProperty(n))
            Object.defineProperty(result, n, { value: constants[n] });

    return result;
}());

* Le proprietà sono di sola lettura, solo se i valori iniziali sono immutabili.


4

JavaScript ES6 (ri) ha introdotto la constparola chiave supportata in tutti i principali browser .

Le variabili dichiarate tramite constnon possono essere ri-dichiarate o riassegnate.

A parte questo, constsi comporta in modo simile a let.

Si comporta come previsto per i tipi di dati primitivi (booleano, null, indefinito, numero, stringa, simbolo):

const x = 1;
x = 2;
console.log(x); // 1 ...as expected, re-assigning fails

Attenzione: prestare attenzione alle insidie ​​relative agli oggetti:

const o = {x: 1};
o = {x: 2};
console.log(o); // {x: 1} ...as expected, re-assigning fails

o.x = 2;
console.log(o); // {x: 2} !!! const does not make objects immutable!

const a = [];
a = [1];
console.log(a); // 1 ...as expected, re-assigning fails

a.push(1);
console.log(a); // [1] !!! const does not make objects immutable

Se hai davvero bisogno di un oggetto immutabile e assolutamente costante: basta usare const ALL_CAPSper chiarire la tua intenzione. È comunque una buona convenzione da seguire per tutte le constdichiarazioni, quindi fai affidamento su di essa.


Solo da IE11 :-(
Mo.

3

Un'altra alternativa è qualcosa di simile:

var constants = {
      MY_CONSTANT : "myconstant",
      SOMETHING_ELSE : 123
    }
  , constantMap = new function ConstantMap() {};

for(var c in constants) {
  !function(cKey) {
    Object.defineProperty(constantMap, cKey, {
      enumerable : true,
      get : function(name) { return constants[cKey]; }
    })
  }(c);
}

Quindi semplicemente: var foo = constantMap.MY_CONSTANT

Se lo facessi constantMap.MY_CONSTANT = "bar"non avrebbe alcun effetto poiché stiamo cercando di utilizzare un operatore di assegnazione con un getter, quindi constantMap.MY_CONSTANT === "myconstant"rimarrebbe vero.


3

in Javascript esistono già costanti . Definisci una costante come questa:

const name1 = value;

Questo non può cambiare attraverso la riassegnazione.


Per il link nella risposta, questa è una funzione sperimentale e dovrebbe essere usata con cautela.
Johnie Karr,

Certo, sono d'accordo con te. Ma nelle ultime versioni dei browser funziona.
Erik Lucio,

3

La parola chiave "const" è stata proposta in precedenza e ora è stata ufficialmente inclusa in ES6. Utilizzando la parola chiave const, è possibile passare un valore / stringa che fungerà da stringa immutabile.


2

L'introduzione di costanti in JavaScript è nella migliore delle ipotesi un trucco.

Un buon modo per rendere persistenti e accessibili globalmente valori in JavaScript sarebbe dichiarare un oggetto letterale con alcune proprietà di "sola lettura" come questa:

            my={get constant1(){return "constant 1"},
                get constant2(){return "constant 2"},
                get constant3(){return "constant 3"},
                get constantN(){return "constant N"}
                }

avrai tutte le tue costanti raggruppate in un unico "mio" oggetto accessorio in cui puoi cercare i tuoi valori memorizzati o qualsiasi altra cosa che potresti aver deciso di mettere lì per quella materia. Ora proviamo se funziona:

           my.constant1; >> "constant 1" 
           my.constant1 = "new constant 1";
           my.constant1; >> "constant 1" 

Come possiamo vedere, la proprietà "my.constant1" ha conservato il suo valore originale. Ti sei fatto delle belle costanti temporanee "verdi" ...

Ma ovviamente questo ti proteggerà solo dalla modifica, dall'alterazione, dall'annullamento o dallo svuotamento accidentale del valore della costante della tua proprietà con un accesso diretto come nell'esempio fornito.

Altrimenti penso ancora che le costanti siano per i manichini. E penso ancora che scambiare la tua grande libertà con un piccolo angolo di sicurezza ingannevole sia il peggior commercio possibile.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.