Gibt es Konstanten in JavaScript?


1132

Gibt es eine Möglichkeit, Konstanten in JavaScript zu verwenden ?

Wenn nicht, wie wird üblicherweise Variablen angegeben, die als Konstanten verwendet werden?


35
ChromeErmöglicht die Verwendung des Schlüsselworts constzur Verwendung von Konstanten. zB const ASDF = "asdf". Da constes jedoch nicht mit mehreren Browsern kompatibel ist, halte ich mich normalerweise an eine varErklärung.
Jacksonkr

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

13
Derek: Würde Ihr Versuch / Fang nicht den Umfang der Sache einschränken, die Sie dem Versuch / Fang-Block deklarieren? Wenn Sie nicht richtig scoping, wozu dann constoder varüberhaupt?
Coderer

8
@Coderer in den aktuellen Implementierungen funktioniert dies, da constes den gleichen Umfang hat wie var, und das ist Funktionsebene, nicht Blockebene. Wenn Sie stattdessen dem bevorstehenden ECMAScript-Standard folgen, consthat er den gleichen Umfang wie let, was bedeutet, dass er nicht funktioniert.
Jasper

3
@Coderer Falsche Sprache. Variablen in Javascript sind Funktionsumfang. Dies ist nicht C.
Doug65536

Antworten:


1018

Seit ES2015 hat JavaScript eine Vorstellung von const:

const MY_CONSTANT = "some-value";

Dies funktioniert in nahezu allen Browsern außer IE 8, 9 und 10 . Für einige muss möglicherweise auch der strikte Modus aktiviert sein.

Sie können varKonventionen wie ALL_CAPS verwenden, um zu zeigen, dass bestimmte Werte nicht geändert werden sollten, wenn Sie ältere Browser unterstützen müssen oder mit Legacy-Code arbeiten:

var MY_CONSTANT = "some-value";

60
Wie wäre es mit const x = 24;
Zachary Scott

93
Beachten Sie, dass Sie das constSchlüsselwort verwenden können, wenn Sie keine browserübergreifende Kompatibilität benötigen (oder wenn Sie serverseitig in Rhino oder Node.js programmieren) . Es wird derzeit von allen modernen Browsern außer IE unterstützt.
Husky

17
In diesen Tagen (3,5 Jahre später) können Sie Object.definePropertyschreibgeschützte Eigenschaften erstellen, die auch nicht gelöscht werden können. Dies funktioniert in der aktuellen Version aller gängigen Browser (jedoch falsch in IE8 ). Siehe die Antwort von @NotAName
Phrogz

12
@ Amyth Das ist nicht wirklich hilfreich. Es ist ein Styleguide, der von einem einzigen Anbieter vorgeschlagen wird. Gemäß dem obigen Punkt von Husky ist die IE-Kompatibilität beim Schreiben von serverseitigem JS völlig irrelevant.
Aendrew

32
Da diese Antwort von Google im Jahr 2015 immer noch einen hohen Stellenwert hat, sollte gesagt werden, dass sie jetzt veraltet ist. Das constSchlüsselwort ist jetzt offiziell Teil der Sprache und wird von jedem Browser unterstützt. Laut statcounter.com verwenden nur noch wenige Prozent der Internetnutzer alte Browserversionen, die nicht unterstützt wurden const.
Tristan

310

Versuchen Sie, die Variablen vor Änderungen zu schützen? Wenn ja, können Sie ein Modulmuster verwenden:

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

Mit diesem Ansatz können die Werte nicht geändert werden. Sie müssen jedoch die Methode get () für CONFIG :( verwenden.

Wenn Sie den Variablenwert nicht streng schützen müssen, gehen Sie einfach wie vorgeschlagen vor und verwenden Sie eine Konvention von ALL CAPS.


13
Beachten Sie, dass Sie einfach eine Funktion für den Wert von CONFIG zurückgeben können. Das erspart Ihnen das ständige Aufrufen von CONFIG.get ().
Mathew Byrne

4
Hübsche Lösung. Solche Dinge sollten jedoch als Bibliothek verpackt werden, um sie in keinem neuen Projekt neu zu erfinden.
Andrii

82
CONFIG.get = someNewFunctionThatBreaksTheCode... Alles in allem können Sie Konstanten in JS (ohne const-Schlüsselwort) absolut nicht erzwingen. Sie können nur die Sichtbarkeit einschränken.
Thomas Eding

28
Ich glaube, das privateist ein zukünftig reserviertes Wort in JavaScript. Ich würde das nicht verwenden, wenn ich Sie wäre.
Zaq

Dies ist auch das Registrierungsmuster.

122

Das constSchlüsselwort befindet sich im Entwurf von ECMAScript 6, wird jedoch bisher nur von wenigen Browsern unterstützt: http://kangax.github.io/compat-table/es6/ . Die Syntax lautet:

const CONSTANT_NAME = 0;

13
Wenn Sie versuchen, a einen Wert zuzuweisen const, werden keine Fehler ausgegeben. Die Zuweisung schlägt einfach fehl und die Konstante hat immer noch ihren ursprünglichen Wert. Dies ist meiner Meinung nach ein großer Konstruktionsfehler, aber solange es eine klare, konsistente Namenskonvention gibt (wie die beliebte ALL_CAPS), denke ich nicht, dass dies zu viel Kummer verursachen würde.
MatrixFrog

6
Behalten Sie die Browserunterstützung hier im Auge: kangax.github.io/es5-compat-table/es6/#const
Mark McDonald

6
Die Zuweisung von @MatrixFrog löst einen Fehler mit aus 'use strict'.
Sam

Soll ich Konstanten in definieren ALL CAPS?
Lewis

1
@Tresdin Es ist eine übliche Namenskonvention, Konstanten in Großbuchstaben zu definieren. Nichts in der Sprachspezifikation erzwingt es, aber es ist keine schlechte Idee. Es macht klarer, was Ihre Absicht ist, und verbessert so die Lesbarkeit des Codes.
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

Siehe Object.freeze . Sie können verwenden,const wenn Sie die constantsReferenz auch schreibgeschützt machen möchten .


2
Sollte erwähnen, dass dies nur unter IE9 + kangax.github.io/compat-table/es5 funktioniert .
Cordle

Ich würde, wenn es nicht die kaputte Implementierung voni
Alnitak

Hinweis: Dies verhält sich ähnlich wie die ES6- constDeklaration, z. B. können Eigenschaften nicht erneut deklariert oder neu zugewiesen werden. Wenn sie jedoch vom Datentyp sind object, können sie mutiert werden.
le_m

Genau das, wonach ich gesucht habe. Sie können auch const constantsanstelle von verwenden var constants, um zu verhindern, dass die Variable neu zugewiesen wird.
Jarett Millard

Siehe z. B. Tiefkühlen für rekursives Einfrieren.
Sam

64

IE unterstützt Konstanten, z. B.:

<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
Junge, rede über etwas, das nicht browserübergreifend ist. . . Immer noch +1 für ein bisschen über den Tellerrand hinaus.
Tom

14
VBScript? Was ist das? ;)
tybro0103

2
Normalerweise stimme ich für allgemeine verwandte Cross-Browser-Fragen mit einer IE-spezifischen Antwort ab. Weil ich Leute hasse, die denken, dass die Implementierung von IE-Javascript "das Eine" ist, und andere einfach ignoriert werden sollen. Wer nutzt übrigens andere Kreditnehmer als IE?
Ameise

@Cooluhuru Dieses Skript scheint sowohl IE-Browser (mit VBScript) als auch Nicht-IE-Browser (mit JavaScript const) zu handhaben . Können Sie erklären, was daran falsch ist?
Andrew Grimm

Es fällt mir immer noch schwer zu akzeptieren, dass Konstanten geändert werden können.
Norbert Norbertson

59

ECMAScript 5 führt ein Object.defineProperty:

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

Es wird in jedem modernen Browser (sowie IE ≥ 9) unterstützt.

Siehe auch: Object.defineProperty in ES5?


1
Es ist erwähnenswert, dass dies nicht wie eine traditionelle Konstante ist. Auf diese Weise können Sie nur eine konstante Eigenschaft (eines nicht konstanten Objekts) definieren. Auch dies erzeugt keinen Fehler und gibt sogar den Wert zurück, den Sie einstellen möchten. Der Wert wird einfach nicht geschrieben.
Cory Gross

3
Vor kurzem las ich , dass mit einer Eigenschaft zuweisen versucht writable: false wird tatsächlich einen Fehler aus , wenn der Code, der die Zuordnung tut , ist unter strengen Modus ECMAScript 5 des interpretiert wird. Nur ein weiterer Grund, 'use strict'in Ihren Code zu schreiben .
Cory Gross

6
Sie können tatsächlich weglassen, writable: falseda dies die Standardeinstellung ist .
Sam

24

Nein, im Allgemeinen nicht. Firefox implementiert, constaber ich weiß, dass IE dies nicht tut.


@John weist auf eine gängige Benennungspraxis für Konstanten hin, die seit Jahren in anderen Sprachen verwendet wird. Ich sehe keinen Grund, warum Sie das nicht verwenden konnten. Das bedeutet natürlich nicht, dass jemand den Wert der Variablen sowieso nicht überschreibt. :) :)


11
Wie jeder weiß, könnte es nicht existieren, wenn der IE es nicht implementiert.
Josh Hinman

3
Leider und praktisch gesehen ist es wahr. IE besitzt einen großen Marktanteil. Wenn ich ein Unternehmen besitze und Webanwendungen intern verwenden würde, würde ich auf FF standardisieren. Ich weiß nicht, warum sich so viele Leute für IE interessieren, es bläst.
Jason Bunting

@ Rich: Wer hat gesagt, dass meine Meinung eine Tatsache ist? Sie haben die Annahme gemacht. Außerdem ist für mich die Tatsache, dass der IE scheiße ist, eine Tatsache. Sie können Ihre eigenen Fakten haben, ich habe nicht gesagt, dass Sie meinen glauben müssen. : P Nehmen Sie einen Xanax oder so ...
Jason Bunting

@Rich B, ja, das war nur ein dummer Kommentar, und vertraue mir, ich würde wissen, ich mache viele dumme Kommentare. @ Jason B. - interessant, ich bin gestern Abend auf genau dieses Problem gestoßen. Const hat in FF gearbeitet, aber nicht im IE. Vielen Dank für die Klarstellung

Wen interessiert der IE? Ich nicht! FF oder Chrome oder Opera usw. können fast auf jeder Betriebssystemplattform installiert werden. Auch Computerhändler wissen normalerweise, dass die alte IE-Version scheiße ist, so dass sie häufig (oder sogar jedes Mal) alternative Browser installieren, bevor sie einen Computer verkaufen. Daher habe ich beschlossen, dass sich meine entwickelte App überhaupt nicht um inkompatible Browser kümmert: Wenn Browserentwickler die Standards einhalten, kann ihr Produkt meine App verwenden. Wenn nicht, verwenden Benutzer einen anderen Browser. Ich kann damit leben. -) Aber kann Microsoft leben und einen Teil des Marktes verlieren? Nein, sie können nicht so "Sie" werden ihre Entwicklungspolitik ändern!
Willy Wonka

20

In JavaScript bevorzuge ich die Verwendung von Funktionen, um konstante Werte zurückzugeben.

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


alert(MY_CONSTANT());

6
Es sei darauf hingewiesen, dass dies in das gleiche Problem fällt, das in der Antwort von @Burkes (Kommentar von @trinithis) erwähnt wurde. `MY_CONSTANT = function () {return" some-other-value "; } bricht es. +1, anständige und schnelle Lösung.
Patrick M

13
-1. Dies hat keinen Vorteil gegenüber var SOME_NAME = value (es ist immer noch veränderbar), ist mehr Code und muss erklärt werden.
Mikemaccana

@PatrickM Obwohl es stimmt, dass Sie diese Art von Pseudokonstanten in anderen Sprachen wie z. B. C ändern können , für die Sie Konstanten nicht ändern sollten, können Sie dies dennoch über z. B. Zeiger tun. Solange Sie also einen Ansatz verwenden, der zumindest darauf hindeutet, dass es sich um eine Konstante handelt, ist dies imo in Ordnung.
Rev.

20

Mozillas MDN-Webdokumente enthalten gute Beispiele und Erklärungen zu const. Auszug:

// 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;

Es ist jedoch traurig, dass IE9 / 10 immer noch nicht unterstützt const. Und der Grund, warum es absurd ist :

Also, was macht IE9 mit const? Bisher haben wir beschlossen, dies nicht zu unterstützen. Es ist noch keine Konsensfunktion, da es noch nie in allen Browsern verfügbar war.

...

Am Ende scheint es die beste langfristige Lösung für das Web zu sein, es wegzulassen und darauf zu warten, dass Standardisierungsprozesse ihren Lauf nehmen.

Sie implementieren es nicht, weil andere Browser es nicht richtig implementiert haben?! Zu ängstlich, es besser zu machen? Standarddefinitionen oder nicht, eine Konstante ist eine Konstante: einmal gesetzt, nie geändert.

Und zu allen Ideen: Jede Funktion kann überschrieben werden (XSS etc.). Es gibt also keinen Unterschied in varoder function(){return}. constist die einzige wirkliche Konstante.

Update: IE11 unterstützt const :

IE11 bietet Unterstützung für die gut definiert und häufig verwendete Funktionen des neuen ECMAScript 6 Standard einschließlich let, const, Map, Set, und WeakMapsowie __proto__für eine verbesserte Interoperabilität.


25
"Es war noch nie in allen Browsern verfügbar". Wenn Sie es nicht im Internet Explorer verfügbar machen, wird es niemals in allen Browsern verfügbar sein.
km1

Fahrstandardisierung ist nicht jedermanns Sache;) - Unternehmen kommen und gehen wieder - danke, dass Sie die Chancen im Wald zitiert haben
schneller

noch eine dazu: VBA ist noch nicht in allen Browsern eine Consesus-Funktion und MS unterstützt const in VBA - dies ist die Beherrschung des Channeling von Entwicklungsbudgets;)
Schneller

17

Wenn es Ihnen nichts ausmacht, Funktionen zu verwenden:

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

Dieser Ansatz bietet Ihnen Funktionen anstelle von regulären Variablen, garantiert jedoch *, dass niemand den Wert ändern kann, sobald er festgelegt ist.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Ich persönlich finde das ziemlich angenehm, besonders nachdem ich mich an dieses Muster von Knockout-Observablen gewöhnt habe.

* Es sei denn, jemand hat die Funktion neu definiert, constantbevor Sie sie aufgerufen haben


1
underscore.js implementiert eine konstante Funktion, die mit diesem Code identisch ist.
Upperstage

Einfach, prägnant und beantwortet den Geist der OP-Frage. Dies sollte mehr upVotes erhalten haben.
Mac

3
Das hat bei mir nie wirklich funktioniert. Auch wenn der Abschluss es unveränderlich macht, kann die Variable, der Sie es zuweisen, dennoch überschrieben werden. Beispiel: a = constant(10); a(10); // 10gefolgt von a = constant(25); a(); //25, keine Fehler oder Warnungen gegeben, kein Hinweis darauf, dass Ihre Konstante gebrochen wurde.
Patrick M.

Wenn ich den Wert neu zuordne, aändert sich der Wert in einen neuen Wert
zuordne

17

Mit der "neuen" Objekt-API können Sie Folgendes tun:

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

werfen Sie einen Blick auf diese auf dem Mozilla MDN für weitere Einzelheiten. Es ist keine Variable der ersten Ebene, da sie an ein Objekt angehängt ist. Wenn Sie jedoch einen Bereich haben, können Sie ihn an diesen anhängen. thissollte auch funktionieren. Wenn Sie dies beispielsweise im globalen Bereich tun, wird im Fenster ein Pseudokonstantenwert deklariert (was eine wirklich schlechte Idee ist, sollten Sie globale Variablen nicht nachlässig deklarieren).

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

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

Hinweis: Durch die Zuweisung erhalten Sie den zugewiesenen Wert in der Konsole zurück, der Wert der Variablen ändert sich jedoch nicht


Funktioniert nicht in Safari und in Mozilla, wenn Sie die Anweisung define erneut ausführen - mit einem anderen Wert - wird der Wert neu zugewiesen.
Akshay

2
Nicht 'nicht in Safari arbeiten', nicht unterstützt in Safari. Nicht das gleiche. Und es sollte einen 'Uncaught TypeError: Eigenschaft kann nicht neu definiert werden: <Eigenschaftsname hier>', wenn Sie das versuchen. Entweder machst du es falsch oder dein ff hat es falsch implementiert. Ich denke, es ist eine Mischung aus beidem.
Tenshou

14

Gruppieren Sie Konstanten nach Möglichkeit in Strukturen:

Beispiel, in meinem aktuellen Spielprojekt, habe ich unten verwendet:

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

Zuordnung:

var wildType = CONST_WILD_TYPES.REGULAR;

Vergleich:

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

In jüngerer Zeit verwende ich zum Vergleich:

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

IE11 ist mit dem neuen ES6-Standard ausgestattet, der über eine 'const'-Deklaration verfügt.
Oben funktioniert in früheren Browsern wie IE8, IE9 und IE10.


12

Sie können Ihr Skript problemlos mit einem Mechanismus für Konstanten ausstatten, der festgelegt, aber nicht geändert werden kann. Ein Versuch, sie zu ändern, führt zu einem Fehler.

/* 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

Vergiss den IE und benutze das constSchlüsselwort.


9
funktioniert bei mir! aber dann schreibe ich eine Chrome-Erweiterung, damit ich weiß, dass ich in einem vernünftigen Browser bin ...
yoyo

1
@yoyo Das Beste am Schreiben von Erweiterungen und Addons - keine browserübergreifende Unterstützung!
Ian

1
@ Ian Willkommen im Jahr 2019, die browserübergreifende Inkonsistenz ist fast verschwunden :)
Fusseldieb

9

Es gibt jedoch keine genaue browserübergreifende vordefinierte Methode. Sie können dies erreichen, indem Sie den Umfang der Variablen steuern, wie in anderen Antworten gezeigt.

Aber ich werde vorschlagen, Namensraum zu verwenden, um von anderen Variablen zu unterscheiden. Dadurch wird die Wahrscheinlichkeit einer Kollision mit anderen Variablen auf ein Minimum reduziert.

Richtiger Namespace wie

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

also während der Verwendung wird es sein iw_constant.nameoderiw_constant.age

Sie können das Hinzufügen eines neuen Schlüssels oder das Ändern eines Schlüssels in iw_constant mithilfe der Object.freeze-Methode auch blockieren. Es wird jedoch nicht von älteren Browsern unterstützt.

Ex:

Object.freeze(iw_constant);

Für ältere Browser können Sie die Polyfill- Methode zum Einfrieren verwenden.


Wenn Sie mit dem Aufrufen der Funktion einverstanden sind, ist das Folgende am besten browserübergreifend, um Konstanten zu definieren. Scoping Ihres Objekts innerhalb einer selbstausführenden Funktion und Rückgabe einer get-Funktion für Ihre Konstanten, z.

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

       };

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

// um den Wert zu erhalten, benutze iw_constant('name')oderiw_constant('age')


** In beiden Beispielen müssen Sie beim Namensabstand sehr vorsichtig sein, damit Ihr Objekt oder Ihre Funktion nicht durch eine andere Bibliothek ersetzt wird. (Wenn das Objekt oder die Funktion selbst ersetzt wird, wird Ihre gesamte Konstante gelöscht.)


7

Für eine Weile habe ich "Konstanten" (die eigentlich noch keine Konstanten waren) in Objektliteralen angegeben, die an with()Anweisungen übergeben wurden. Ich fand es so klug. Hier ist ein Beispiel:

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

In der Vergangenheit habe ich auch einen CONSTNamespace erstellt, in den ich alle meine Konstanten eingefügt habe. Wieder mit dem Overhead. Meine Güte.

Nun, ich weiß nur var MY_CONST = 'whatever';zu KISS .


16
Wenn es etwas Böseres als Eval gibt, ist es definitiv with.
NikiC

4
eval ist sehr böse! Es hat mein Haus einmal niedergebrannt!
W3Geek

6

Meine Meinung (funktioniert nur mit Objekten).

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

Versuchen! Aber verstehe - das ist ein Objekt, aber keine einfache Variable.

Versuchen Sie auch einfach:

const a = 9;

5

Ich hatte auch ein Problem damit. Und nachdem ich eine ganze Weile nach der Antwort gesucht und alle Antworten von allen betrachtet habe, denke ich, dass ich eine tragfähige Lösung dafür gefunden habe.

Es scheint, dass die meisten Antworten, auf die ich gestoßen bin, Funktionen zum Halten der Konstanten verwenden. Wie viele Benutzer der VIELEN Foren berichten, können die Funktionen von Benutzern auf der Clientseite leicht überschrieben werden. Ich war fasziniert von Keith Evetts Antwort, dass auf das Konstantenobjekt nicht von außen zugegriffen werden kann, sondern nur von den Funktionen auf der Innenseite.

Also habe ich mir diese Lösung ausgedacht:

Fügen Sie alles in eine anonyme Funktion ein, damit die Variablen, Objekte usw. vom Client nicht geändert werden können. Verstecken Sie auch die "echten" Funktionen, indem andere Funktionen die "echten" Funktionen von innen aufrufen. Ich dachte auch daran, Funktionen zu verwenden, um zu überprüfen, ob eine Funktion von einem Benutzer auf der Clientseite geändert wurde. Wenn die Funktionen geändert wurden, ändern Sie sie mithilfe von Variablen, die innen 'geschützt' sind und nicht geändert werden können.

/*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);
  };
}())

Es scheint auch, dass Sicherheit wirklich ein Problem ist und es keine Möglichkeit gibt, Ihre Programmierung auf der Clientseite zu "verbergen". Eine gute Idee für mich ist es, Ihren Code so zu komprimieren, dass es für jeden, einschließlich Sie, den Programmierer, wirklich schwierig ist, ihn zu lesen und zu verstehen. Es gibt eine Website, die Sie besuchen können: http://javascriptcompressor.com/ . (Dies ist nicht meine Website, keine Sorge, ich mache keine Werbung.) Auf dieser Website können Sie Javascript-Code kostenlos komprimieren und verschleiern.

  1. Kopieren Sie den gesamten Code im obigen Skript und fügen Sie ihn in den oberen Textbereich auf der Seite javascriptcompressor.com ein.
  2. Aktivieren Sie das Kontrollkästchen Base62-Codierung und das Kontrollkästchen Variablen verkleinern.
  3. Drücken Sie die Komprimiertaste.
  4. Fügen Sie alles ein, speichern Sie es in einer .js-Datei und fügen Sie es Ihrer Seite im Kopf Ihrer Seite hinzu.

Dies ist eine gute Lösung, die sich gut als Bibliothek einbinden lässt. Aber ich mag die Benennung Ihrer Variablen in diesem Code nicht. Warum sollten Sie die beschreibenden Namen wie "Name" und "Wert", wie sie in Keiths Code verwendet werden, löschen? Kleines Problem, aber immer noch.
Cordle

5

Dies zeigt deutlich die Notwendigkeit eines standardisierten browserübergreifenden const-Schlüsselworts.

Aber für den Moment:

var myconst = value;

oder

Object['myconst'] = value;

Beides scheint ausreichend zu sein und alles andere ist wie das Schießen einer Fliege mit einer Panzerfaust.


nimm den guten alten var myconst = value; und zum Debuggen verwenden Sie zusätzlichen Debugging-Code ... - funktioniert wie verrückt, solange nicht alle Browser const unterstützen
schneller

4

Ich verwende conststatt varin meinen Greasemonkey-Skripten, aber es liegt daran, dass sie nur unter Firefox ausgeführt werden ... Die
Namenskonvention kann in der Tat auch der richtige Weg sein (ich mache beides!).


4

In JavaScript bestand meine Praxis darin, Konstanten so weit wie möglich zu vermeiden und stattdessen Zeichenfolgen zu verwenden. Probleme mit Konstanten treten auf, wenn Sie Ihre Konstanten der Außenwelt aussetzen möchten:

Zum Beispiel könnte man die folgende Datums-API implementieren:

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

Aber es ist viel kürzer und natürlicher, einfach zu schreiben:

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

Auf diese Weise verhalten sich "Tage" und "Stunden" wirklich wie Konstanten, da Sie von außen nicht ändern können, wie viele Sekunden "Stunden" darstellen. Aber es ist leicht zu überschreiben MyModule.Date.HOUR.

Diese Art von Ansatz hilft auch beim Debuggen. Wenn Firebug Ihnen sagt, dass action === 18es ziemlich schwer ist herauszufinden, was es bedeutet, aber wenn Sie es sehen, action === "save"ist es sofort klar.


Es ist leider ziemlich einfach, Rechtschreibfehler zu machen - z. B. "Hours"statt "hours"-, aber eine IDE kann Sie frühzeitig darüber informieren, dass dies Date.Hoursnicht definiert ist.
le_m

4

Okay, das ist hässlich, aber es gibt mir eine Konstante in Firefox und Chromium, eine inkonstante Konstante (WTF?) In Safari und Opera und eine Variable in IE.

Natürlich ist eval () böse, aber ohne es gibt IE einen Fehler aus, der die Ausführung von Skripten verhindert.

Safari und Opera unterstützen das Schlüsselwort const, Sie können jedoch den Wert der Konstante ändern .

In diesem Beispiel schreibt serverseitiger Code JavaScript auf die Seite und ersetzt {0} durch einen Wert.

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);

Wofür ist das gut? Nicht viel, da es nicht browserübergreifend ist. Bestenfalls vielleicht ein wenig Ruhe, zumindest einige Browser nicht zulassen, dass Lesezeichen oder Skripte von Drittanbietern den Wert ändern.

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


1
Ich liebe diesen Code! Hässlich wie zum Teufel, aber ein guter Test für die Unterstützung von Konstanten. =)
Stein G. Strindhaug

1
etwas lustig, ey - wie viele Zeilen können Sie eingeben, um eine Konstante zu deklarieren?
Schneller

4

Wenn es erwähnenswert ist, können Sie Konstanten im Winkel mit definieren$provide.constant()

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

... und Sie können const in VBA verwenden ... xbrowser? ... ups ...;)
Schneller

OP fragt nach Javascript und beantwortet Angebote mit einem bestimmten JS-Framework mit starker Meinung. Praktisch nicht zum Thema.
Rounce

2
@rounce: Off-Topic-Antworten sind immer noch Antworten. Kennzeichnen Sie sie nicht als Keine Antwort, sondern stimmen Sie ab und stimmen Sie ab, um sie stattdessen zu löschen . Siehe Wie verwende ich das Flag "Keine Antwort" richtig?
Kevin Guan

@ KevinGuan Noted, wird in Zukunft tun.
Rounce

4

Eine verbesserte Version von Burkes Antwort , mit der Sie CONFIG.MY_CONSTstatt CONFIG.get('MY_CONST').

Es erfordert IE9 + oder einen echten Webbrowser.

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;
}());

* Die Eigenschaften sind nur dann schreibgeschützt, wenn die Anfangswerte unveränderlich sind.


4

JavaScript ES6 hat das constSchlüsselwort (neu) eingeführt, das in allen gängigen Browsern unterstützt wird .

Über deklarierte Variablen constkönnen nicht erneut deklariert oder neu zugewiesen werden.

Abgesehen davon constverhält sich ähnlich wie let.

Es verhält sich wie erwartet für primitive Datentypen (Boolean, Null, Undefined, Number, String, Symbol):

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

Achtung: Beachten Sie die Fallstricke bei Objekten:

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

Wenn Sie wirklich ein unveränderliches und absolut konstantes Objekt benötigen: Verwenden Sie es einfach const ALL_CAPS, um Ihre Absicht klar zu machen. Es ist constsowieso eine gute Konvention, alle Erklärungen einzuhalten, also verlassen Sie sich einfach darauf.


Nur von IE11 :-(
Mo.

3

Eine andere Alternative ist so etwas wie:

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);
}

Dann einfach: var foo = constantMap.MY_CONSTANT

Wenn Sie dazu constantMap.MY_CONSTANT = "bar"wären, hätte dies keine Auswirkung, da wir versuchen, einen Zuweisungsoperator mit einem Getter zu verwenden, und constantMap.MY_CONSTANT === "myconstant"würde daher wahr bleiben.


3

In Javascript gibt es bereits Konstanten . Sie definieren eine Konstante wie folgt:

const name1 = value;

Dies kann sich nicht durch Neuzuweisung ändern.


Laut dem Link in der Antwort ist dies eine experimentelle Funktion und sollte mit Vorsicht verwendet werden.
Johnie Karr

Natürlich stimme ich Ihnen zu. Aber in den letzten Versionen von Browsern funktioniert es.
Erik Lucio

3

Das Schlüsselwort 'const' wurde früher vorgeschlagen und jetzt offiziell in ES6 aufgenommen. Mit dem Schlüsselwort const können Sie einen Wert / eine Zeichenfolge übergeben, die als unveränderliche Zeichenfolge fungiert.


2

Das Einführen von Konstanten in JavaScript ist bestenfalls ein Hack.

Eine gute Möglichkeit, dauerhafte und global zugängliche Werte in JavaScript zu erstellen, besteht darin, ein Objektliteral mit einigen schreibgeschützten Eigenschaften wie diesen zu deklarieren:

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

Sie haben alle Ihre Konstanten in einem einzigen "my" -Zubehörobjekt zusammengefasst, in dem Sie nach Ihren gespeicherten Werten oder anderen Elementen suchen können, die Sie möglicherweise dort abgelegt haben. Testen wir nun, ob es funktioniert:

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

Wie wir sehen können, hat die Eigenschaft "my.constant1" ihren ursprünglichen Wert beibehalten. Sie haben sich einige schöne 'grüne' temporäre Konstanten gemacht ...

Dies schützt Sie jedoch natürlich nur davor, Ihren Wert für die Eigenschaftskonstante versehentlich mit einem direkten Zugriff wie im angegebenen Beispiel zu ändern, zu ändern, aufzuheben oder zu leeren.

Ansonsten denke ich immer noch, dass Konstanten für Dummies sind. Und ich denke immer noch, dass der Austausch Ihrer großen Freiheit gegen eine kleine Ecke trügerischer Sicherheit der schlechteste Handel ist, der möglich ist.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.