Apakah ada konstanta dalam JavaScript?

1132

Apakah ada cara untuk menggunakan konstanta dalam JavaScript ?

Jika tidak, apa praktik umum untuk menentukan variabel yang digunakan sebagai konstanta?

fuentesjr
sumber
35
Chromememungkinkan Anda menggunakan kata kunci constuntuk menggunakan konstanta. mis const ASDF = "asdf". Namun, karena consttidak multi-browser yang kompatibel, saya biasanya tetap dengan vardeklarasi.
Jacksonkr
20
try{const thing=1091;}catch(e){var thing=1091;}bekerja.
Derek 朕 會 功夫
13
Derek: tidak akankah coba / tangkapan Anda membatasi ruang lingkup hal yang Anda deklarasikan ke blok coba / tangkap? Jika Anda tidak melakukan pelingkupan dengan benar maka apa gunanya menentukan constatau tidak varsama sekali?
Coderer
8
@Coderer dalam implementasi saat ini, ini akan berfungsi, karena constmemiliki cakupan yang sama dengan var, dan itu adalah level-fungsi, bukan level-blok. Jika Anda mengikuti standar ECMAScript mendatang, constmemiliki cakupan yang sama dengan let, yang berarti tidak akan berfungsi.
Jasper
3
@Coderer Bahasa salah. Variabel dalam javascript adalah ruang lingkup fungsi. Ini bukan C.
doug65536

Jawaban:

1018

Sejak ES2015 , JavaScript memiliki gagasan tentang const:

const MY_CONSTANT = "some-value";

Ini akan bekerja di hampir semua browser kecuali IE 8, 9 dan 10 . Beberapa mungkin juga membutuhkan mode ketat diaktifkan.

Anda dapat menggunakan vardengan konvensi seperti ALL_CAPS untuk menunjukkan bahwa nilai-nilai tertentu tidak boleh dimodifikasi jika Anda perlu mendukung browser lama atau bekerja dengan kode lawas:

var MY_CONSTANT = "some-value";
John Millikin
sumber
60
Bagaimana dengan const x = 24;
Zachary Scott
93
Perhatikan bahwa jika Anda tidak memerlukan kompatibilitas lintas-browser (atau Anda pemrograman di sisi server dalam Rhino atau Node.js) Anda dapat menggunakan constkata kunci. Saat ini didukung oleh semua browser modern kecuali untuk IE.
Husky
17
Saat ini (3,5 tahun kemudian), Anda dapat menggunakan Object.definePropertyuntuk membuat properti hanya-baca yang juga tidak dapat dihapus. Ini berfungsi di versi saat ini dari semua browser utama (tetapi salah di IE8 ). Lihat jawabannya oleh @NotAName
Phrogz
12
@ Mitos Itu tidak terlalu membantu. Ini adalah panduan gaya yang diusulkan oleh vendor tunggal. Sesuai poin Husky di atas, kompatibilitas IE sama sekali tidak relevan ketika menulis JS server-side.
aendrew
32
Karena jawaban ini masih berperingkat tinggi oleh Google pada tahun 2015 maka harus dikatakan bahwa itu sudah usang. Kata constkunci sekarang secara resmi bagian dari bahasa dan didukung oleh setiap browser. Menurut statcounter.com, hanya beberapa persen pengguna internet yang masih menggunakan versi browser lama yang tidak mendukung const.
tristan
310

Apakah Anda mencoba melindungi variabel terhadap modifikasi? Jika demikian, maka Anda dapat menggunakan pola modul:

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

Dengan menggunakan pendekatan ini, nilai-nilai tidak dapat dimodifikasi. Tapi, Anda harus menggunakan metode get () di CONFIG :(.

Jika Anda tidak perlu secara ketat melindungi nilai variabel, maka lakukan saja seperti yang disarankan dan gunakan konvensi ALL CAPS.

Menutup perkara
sumber
13
Perhatikan bahwa Anda bisa mengembalikan fungsi untuk nilai CONFIG. Itu akan menghemat Anda memanggil CONFIG.get () sepanjang waktu.
Mathew Byrne
4
Solusi yang bagus. Tetapi hal-hal seperti itu harus dibungkus sebagai perpustakaan untuk tidak menemukan kembali mereka dalam proyek baru.
andrii
82
CONFIG.get = someNewFunctionThatBreaksTheCode... Semua dalam semua, Anda benar-benar tidak dapat menegakkan konstanta di JS (tanpa kata kunci const). Satu-satunya hal yang dapat Anda lakukan adalah membatasi visibilitas.
Thomas Eding
28
Saya percaya itu privateadalah kata cadangan masa depan dalam JavaScript, saya tidak akan menggunakannya jika saya adalah Anda.
Zaq
Ini juga merupakan pola registri.
122

Kata constkunci dalam draft 6 ECMAScript tetapi sejauh ini hanya menikmati segelintir dukungan browser: http://kangax.github.io/compat-table/es6/ . Sintaksnya adalah:

const CONSTANT_NAME = 0;
Bill the Lizard
sumber
13
Jika Anda mencoba untuk menetapkan nilai ke const, itu tidak menimbulkan kesalahan. Tugas baru saja gagal dan konstanta masih memiliki nilai aslinya. Ini adalah cacat desain IMHO utama tetapi selama ada konvensi penamaan yang jelas dan konsisten (seperti ALL_CAPS populer) Saya tidak berpikir itu akan menyebabkan terlalu banyak kesedihan.
MatrixFrog
6
Mengawasi dukungan browser di sini: kangax.github.io/es5-compat-table/es6/#const
Mark McDonald
6
Penugasan @MatrixFrog akan menimbulkan kesalahan 'use strict'.
sam
Haruskah saya mendefinisikan konstanta ALL CAPS?
Lewis
1
@ Tetresd Ini adalah konvensi penamaan umum untuk mendefinisikan konstanta dalam semua huruf besar. Tidak ada dalam spesifikasi bahasa yang memaksanya, tapi itu bukan ide yang buruk. Itu membuatnya lebih jelas apa maksud Anda, sehingga meningkatkan keterbacaan kode.
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

Lihat Object.freeze . Anda dapat menggunakanconst jika Anda ingin membuat constantsreferensi hanya-baca juga.

sam
sumber
2
Harus menyebutkan ini hanya berfungsi di IE9 + kangax.github.io/compat-table/es5 .
Cordle
Saya akan, jika tidak memiliki implementasi yang rusak darii
Alnitak
Catatan: ini berperilaku mirip dengan constdeklarasi ES6 , misalnya properti tidak dapat dideklarasikan ulang atau ditugaskan kembali, tetapi jika mereka bertipe data object, mereka dapat dimutasi.
le_m
Persis apa yang saya cari. Anda juga bisa menggunakan const constantsalih-alih var constantsuntuk mencegah penugasan kembali variabel.
Jarett Millard
Lihat, misalnya, deep-freeze untuk pembekuan rekursif.
sam
64

IE tidak mendukung konstanta, semacam, misalnya:

<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>
C Nagle
sumber
50
Boy, bicara tentang sesuatu yang bukan browser lintas. . . Masih memberi +1 untuk sedikit berpikir di luar kotak.
Tom
14
VBScript? Apa itu? ;)
tybro0103
2
Saya biasanya memilih untuk pertanyaan lintas browser terkait umum, dengan jawaban khusus IE. Karena saya membenci orang yang berpikir bahwa implementasi javascript IE adalah 'Yang Satu', dan yang lain hanya untuk diabaikan. Siapa yang menggunakan borwser lain selain IE, btw?
Semut
@Cooluhuru skrip ini tampaknya menangani kedua browser IE (menggunakan VBScript) dan browser non-IE (menggunakan JavaScript const). Bisakah Anda menjelaskan apa yang salah dengannya?
Andrew Grimm
Saya masih kesulitan menerima bahwa konstanta dapat diubah.
Norbert Norbertson
59

ECMAScript 5 memperkenalkan Object.defineProperty:

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

Ini didukung di setiap browser modern (serta IE ≥ 9).

Lihat juga: Object.defineProperty di ES5?

Bukan Nama
sumber
1
Perlu dicatat bahwa ini tidak seperti konstanta tradisional. Ini hanya akan memungkinkan Anda untuk mendefinisikan properti konstan (dari objek yang tidak konstan). Ini juga tidak menghasilkan kesalahan dan bahkan mengembalikan nilai yang Anda coba setel. Itu hanya tidak menulis nilai.
Cory Gross
3
Saya baru-baru ini membaca bahwa mencoba untuk menugaskan ke sebuah properti dengan benar writable: false - benar akan menimbulkan kesalahan jika kode yang melakukan penugasan tersebut ditafsirkan dalam mode ketat ECMAScript 5. Hanya alasan lain untuk menuliskan 'use strict'kode Anda.
Cory Gross
6
Anda benar-benar dapat menghilangkan writable: falsekarena itu defaultnya .
sam
24

Tidak, tidak secara umum. Firefox mengimplementasikan consttetapi saya tahu IE tidak.


@ John menunjuk ke praktik penamaan yang umum untuk const yang telah digunakan selama bertahun-tahun dalam bahasa lain, saya tidak melihat alasan mengapa Anda tidak bisa menggunakannya. Tentu saja itu tidak berarti seseorang tidak akan menulis lebih dari nilai variabel. :)

Jason Bunting
sumber
11
Seperti semua orang tahu, jika IE tidak mengimplementasikannya, mungkin juga tidak ada.
Josh Hinman
3
Sayangnya, dan secara praktis berbicara - itu benar. IE memang memiliki pangsa pasar yang besar. Jika saya memiliki bisnis dan memiliki aplikasi web yang digunakan secara internal, saya akan melakukan standarisasi pada FF. Saya tidak tahu mengapa begitu banyak orang peduli tentang IE, itu meledak.
Jason Bunting
@ Rich: Siapa bilang pendapat saya adalah fakta? Anda membuat asumsi yang cukup. Selain itu, sejauh yang saya ketahui, fakta bahwa IE menyebalkan adalah fakta. Anda dapat memiliki fakta sendiri, saya tidak mengatakan Anda harus percaya pada saya. : P Ambil Xanax atau apalah ...
Jason Bunting
@ Rich B, ya itu hanya komentar bodoh untuk dibuat, dan percayalah, saya akan tahu, saya membuat banyak komentar bodoh. @Jason B. - menarik, saya mengalami masalah ini tadi malam .. const bekerja di FF tetapi tidak IE. Terima kasih atas klarifikasi
Siapa yang peduli dengan IE? Bukan saya! FF atau Chrome atau Opera dll ... dapat diinstal hampir di setiap platform OS. Pengecer komputer juga biasanya tahu versi IE lama yang menyebalkan sehingga mereka sering (atau bahkan setiap kali) menginstal browser alternatif sebelum menjual komputer. Jadi saya telah memutuskan untuk aplikasi saya yang dikembangkan untuk tidak peduli sama sekali tentang browser yang tidak kompatibel: jika pengembang browser peduli dengan menghormati standar produk mereka dapat menggunakan aplikasi saya, jika tidak, pengguna akan menggunakan browser yang berbeda ... saya bisa hidup dengan itu; -) Tetapi bisakah Microsoft hidup kehilangan bagian dari pasar? Tidak, mereka tidak bisa begitu "Mereka" akan mengubah politik dev mereka!
willy wonka
20

Dalam JavaScript, preferensi saya adalah menggunakan fungsi untuk mengembalikan nilai konstan.

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


alert(MY_CONSTANT());
MTS
sumber
6
Layak menunjukkan bahwa ini jatuh ke masalah yang sama yang disebutkan dalam jawaban @ Burkes (komentar @trinithis). `MY_CONSTANT = function () {return" some-other-value "; } hancurkan. +1, solusi yang layak dan cepat.
Patrick M
13
-1. Ini tidak memiliki keuntungan dibandingkan var SOME_NAME = nilai (masih bisa berubah), lebih banyak kode, dan perlu dijelaskan.
mikemaccana
@PatrickM sementara memang benar bahwa Anda dapat memodifikasi konstanta semu semacam itu, dalam bahasa lain seperti misalnya C, di mana Anda seharusnya tidak dapat memodifikasi konstanta, Anda masih bisa melakukannya melalui pointer misalnya. Jadi, selama Anda menggunakan beberapa pendekatan yang setidaknya menunjukkan bahwa itu adalah konstan, tidak masalah.
rev
20

Mozillas MDN Web Documents berisi contoh dan penjelasan yang bagus tentang const. Kutipan:

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

Tapi itu menyedihkan bahwa IE9 / 10 masih tidak mendukung const. Dan alasan itu tidak masuk akal :

Jadi, apa yang dilakukan IE9 dengan const? Sejauh ini, keputusan kami adalah untuk tidak mendukungnya. Ini belum fitur konsensus karena belum pernah tersedia di semua browser.

...

Pada akhirnya, sepertinya solusi jangka panjang terbaik untuk web adalah meninggalkannya dan menunggu proses standarisasi untuk menjalankan program mereka.

Mereka tidak mengimplementasikannya karena browser lain tidak menerapkannya dengan benar ?! Terlalu takut membuatnya lebih baik? Definisi standar atau tidak, konstanta adalah konstanta: diset sekali, tidak pernah berubah.

Dan untuk semua ide: Setiap fungsi dapat ditimpa (XSS dll.). Jadi tidak ada perbedaan dalam varatau function(){return}. constadalah satu-satunya konstanta yang nyata.

Pembaruan: IE11 mendukung const :

IE11 termasuk dukungan untuk fitur yang jelas dan umum digunakan dari munculnya ECMAScript 6 standar termasuk let, const, Map, Set, dan WeakMap, serta __proto__untuk meningkatkan interoperabilitas.

mgutt
sumber
25
"belum pernah tersedia di semua browser". Jika Anda tidak membuatnya tersedia di IE maka itu tidak akan pernah ada di semua browser.
km1
mengemudikan standardisasi bukan untuk semua orang;) - perusahaan datang dan mereka pergi lagi - terima kasih telah mengutip peluang di hutan
Lebih cepat
satu lagi tentang ini: VBA bukan fitur consesus di semua browser dan MS mendukung const di VBA - ini adalah penguasaan penyaluran anggaran pengembangan;)
Lebih cepat
17

Jika Anda tidak keberatan menggunakan fungsi:

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

Pendekatan ini memberi Anda fungsi alih-alih variabel biasa, tetapi menjamin * bahwa tidak ada yang dapat mengubah nilai begitu ditetapkan.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Saya pribadi menemukan ini agak menyenangkan, terutama setelah terbiasa dengan pola ini dari KO yang dapat diamati.

* Kecuali seseorang mendefinisikan ulang fungsi constantsebelum Anda menyebutnya

Hasen
sumber
1
underscore.js mengimplementasikan fungsi konstan yang identik dengan kode ini.
Upperstage
Sederhana, ringkas dan menjawab semangat pertanyaan OP. Ini seharusnya menerima lebih banyak Suara.
Mac
3
Ini tidak pernah benar-benar bekerja untuk saya. Meskipun penutupan membuatnya tidak berubah, var yang Anda tetapkan masih bisa ditimpa. Mis: a = constant(10); a(10); // 10diikuti oleh a = constant(25); a(); //25, tidak ada kesalahan atau peringatan yang diberikan, tidak ada indikasi bahwa konstanta Anda telah rusak.
Patrick M
Jika saya menetapkan kembali nilai untuk amaka itu berubah menjadi nilai baru
Saurabh Sharma
17

dengan api objek "baru" Anda dapat melakukan sesuatu seperti ini:

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

lihat ini di Mozilla MDN untuk lebih spesifik. Ini bukan variabel tingkat pertama, karena dilampirkan ke objek, tetapi jika Anda memiliki cakupan, apa pun, Anda dapat melampirkannya ke sana. thisharus bekerja juga. Jadi misalnya melakukan ini dalam lingkup global akan mendeklarasikan nilai konstan semu di jendela (yang merupakan ide yang sangat buruk, Anda tidak boleh mendeklarasikan global vars dengan sembrono)

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

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

catatan: tugas akan memberi Anda kembali nilai yang ditugaskan di konsol, tetapi nilai variabel tidak akan berubah

tenshou
sumber
Tidak bekerja di safari, dan di mozilla jika Anda menjalankan pernyataan define lagi - dengan nilai yang berbeda - itu akan menugaskan kembali nilainya.
Akshay
2
Tidak 'tidak bekerja di safari', tidak didukung di safari. Tidak sama. Dan itu harus membuang 'UnEught TypeError: Tidak dapat mendefinisikan ulang properti: <nama properti di sini>' jika Anda mencobanya. baik Anda salah melakukannya, atau ff Anda menerapkannya dengan tidak benar. Saya kira itu campuran keduanya.
tenshou
14

Konstanta kelompok ke dalam struktur jika memungkinkan:

Contoh, dalam proyek game saya saat ini, saya telah menggunakan di bawah ini:

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

Tugas:

var wildType = CONST_WILD_TYPES.REGULAR;

Perbandingan:

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

Baru-baru ini saya menggunakan, untuk perbandingan:

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

IE11 dengan standar ES6 baru yang memiliki deklarasi 'const'.
Di atas berfungsi di browser sebelumnya seperti IE8, IE9 & IE10.

Manohar Reddy Poreddy
sumber
12

Anda dapat dengan mudah melengkapi skrip Anda dengan mekanisme untuk konstanta yang dapat diatur tetapi tidak diubah. Upaya untuk mengubahnya akan menghasilkan kesalahan.

/* 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  
Keith
sumber
12

Lupakan IE dan gunakan constkata kunci.

Derek 朕 會 功夫
sumber
9
bekerja untukku! tapi kemudian saya menulis ekstensi chrome, jadi saya tahu saya menggunakan browser yang waras ...
yoyo
1
@Yoyo bagian terbaik tentang menulis ekstensi dan addon - tidak ada dukungan lintas browser!
Ian
1
@Ian Selamat datang di 2019, inkonsistensi lintas-browser hampir menghilang :)
Fusseldieb
9

Namun tidak ada cara yang pasti untuk melakukan cross browser, Anda dapat mencapainya dengan mengendalikan ruang lingkup variabel seperti yang ditunjukkan pada jawaban lain.

Tetapi saya akan menyarankan untuk menggunakan ruang nama untuk membedakan dari variabel lain. ini akan mengurangi kemungkinan tabrakan ke minimum dari variabel lain.

Seperti namespace yang tepat

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

jadi saat menggunakannya akan iw_constant.nameatauiw_constant.age

Anda juga dapat memblokir menambahkan kunci baru atau mengubah kunci apa pun di dalam iw_constant menggunakan metode Object.freeze. Namun itu tidak didukung pada browser lawas.

ex:

Object.freeze(iw_constant);

Untuk browser yang lebih lama, Anda dapat menggunakan metode polyfill untuk membekukan.


Jika Anda setuju dengan fungsi panggilan berikut ini adalah cara terbaik lintas browser untuk menetapkan konstanta. Mencakup objek Anda dalam fungsi yang dijalankan sendiri dan mengembalikan fungsi get untuk konstanta Anda, ex:

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

       };

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

// untuk mendapatkan penggunaan nilai iw_constant('name')atauiw_constant('age')


** Dalam kedua contoh, Anda harus sangat berhati-hati dalam penamaan nama sehingga objek atau fungsi Anda tidak boleh diganti melalui perpustakaan lain. (Jika objek atau fungsi itu sendiri akan diganti seluruh konstanta Anda akan hilang)

Sudhanshu Yadav
sumber
7

Untuk sementara, saya menetapkan "konstanta" (yang masih belum benar-benar konstan) dalam objek literal diteruskan ke with()pernyataan. Saya pikir itu sangat pintar. Ini sebuah contoh:

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

Di masa lalu, saya juga telah membuat CONSTnamespace di mana saya akan meletakkan semua konstanta saya. Sekali lagi, dengan biaya overhead. Sheesh.

Sekarang, saya hanya melakukan var MY_CONST = 'whatever';untuk Kiss .

Andrew Hedges
sumber
16
Jika ada sesuatu yang lebih jahat daripada eval, itu pasti with.
NikiC
4
eval sangat jahat! Itu membakar rumah saya satu kali!
W3Geek
6

Pendapat saya (hanya bekerja dengan objek).

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

Mencoba! Tapi mengerti - ini adalah objek, tetapi bukan variabel sederhana.

Coba juga:

const a = 9;
pengguna1635543
sumber
5

Saya juga punya masalah dengan ini. Dan setelah cukup lama mencari jawaban dan melihat semua tanggapan oleh semua orang, saya pikir saya telah menemukan solusi yang layak untuk ini.

Tampaknya sebagian besar jawaban yang saya temui menggunakan fungsi untuk memegang konstanta. Seperti banyak pengguna posting forum BANYAK tentang, fungsi dapat dengan mudah ditulis oleh pengguna di sisi klien. Saya tertarik dengan jawaban Keith Evetts bahwa objek konstanta tidak dapat diakses oleh luar, tetapi hanya dari fungsi di dalam.

Jadi saya datang dengan solusi ini:

Letakkan semuanya di dalam fungsi anonim sehingga variabel, objek, dll. Tidak dapat diubah oleh sisi klien. Sembunyikan juga fungsi 'nyata' dengan meminta fungsi lain memanggil fungsi 'nyata' dari dalam. Saya juga berpikir untuk menggunakan fungsi untuk memeriksa apakah suatu fungsi telah diubah oleh pengguna di sisi klien. Jika fungsi telah diubah, ubah kembali menggunakan variabel yang 'dilindungi' di bagian dalam dan tidak dapat diubah.

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

Tampaknya juga keamanan benar-benar masalah dan tidak ada cara untuk 'menyembunyikan' pemrograman Anda dari sisi klien. Ide bagus bagi saya adalah mengompres kode Anda sehingga sangat sulit bagi siapa pun, termasuk Anda, programmer, untuk membaca dan memahaminya. Ada situs yang bisa Anda kunjungi: http://javascriptcompressor.com/ . (Ini bukan situs saya, jangan khawatir saya tidak beriklan.) Ini adalah situs yang akan memungkinkan Anda mengompres dan mengaburkan kode Javascript secara gratis.

  1. Salin semua kode dalam skrip di atas dan tempel ke dalam textarea teratas di halaman javascriptcompressor.com.
  2. Centang kotak centang encode Base62, centang kotak centang Susutkan Variabel.
  3. Tekan tombol Kompres.
  4. Rekatkan dan simpan semuanya dalam file .js dan tambahkan ke halaman Anda di bagian atas halaman Anda.
Steven Kapaun
sumber
Ini adalah solusi yang baik yang bisa dibungkus dengan baik sebagai perpustakaan untuk dimasukkan. Tapi saya tidak suka penamaan variabel Anda dalam kode ini. Mengapa menjatuhkan nama deskriptif seperti "nama" dan "nilai" seperti yang digunakan dalam kode Keith? Masalah kecil, tapi tetap saja.
Cordle
5

Jelas ini menunjukkan perlunya kata kunci const cross-browser standar.

Tetapi untuk sekarang:

var myconst = value;

atau

Object['myconst'] = value;

Keduanya tampak memadai dan yang lainnya seperti menembak lalat dengan bazoka.

pembuat kode
sumber
ambil var myconst = nilai yang lama; dan untuk debugging, gunakan kode debug tambahan ... - bekerja gila-gilaan selama tidak semua browser mendukung const
Lebih cepat
4

Saya menggunakan constbukannya vardalam skrip Greasemonkey saya, tetapi itu karena mereka akan berjalan hanya pada Firefox ...
Konvensi nama memang bisa menjadi cara untuk pergi juga (saya melakukan keduanya!).

PhiLho
sumber
4

Dalam JavaScript, praktik saya adalah menghindari konstanta sebanyak yang saya bisa dan menggunakan string. Masalah dengan konstanta muncul ketika Anda ingin mengekspos konstanta Anda ke dunia luar:

Misalnya seseorang dapat mengimplementasikan API Tanggal berikut:

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

Tetapi jauh lebih pendek dan lebih alami untuk hanya menulis:

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

Dengan cara ini "hari" dan "jam" benar-benar bertindak seperti konstanta, karena Anda tidak dapat mengubah dari luar berapa banyak yang diwakili oleh "jam". Tapi itu mudah ditimpa MyModule.Date.HOUR.

Pendekatan semacam ini juga akan membantu dalam debugging. Jika Firebug memberi tahu Anda action === 18, cukup sulit untuk mencari tahu apa artinya itu, tetapi ketika Anda melihatnya action === "save"maka segera jelas.

Rene Saarsoo
sumber
Sayangnya cukup mudah untuk membuat kesalahan pengejaan - misal "Hours"alih-alih "hours"- tetapi sebuah IDE mungkin memberi tahu Anda sejak awal bahwa Date.Hoursitu tidak didefinisikan.
le_m
4

Oke, ini jelek, tapi itu memberi saya konstanta di Firefox dan Chromium, konstanta tidak konstan (WTF?) Di Safari dan Opera, dan variabel di IE.

Tentu saja eval () adalah jahat, tetapi tanpa itu, IE melempar kesalahan, mencegah skrip berjalan.

Safari dan Opera mendukung kata kunci const, tetapi Anda dapat mengubah nilai const .

Dalam contoh ini, kode sisi server menulis JavaScript ke halaman, menggantikan {0} dengan sebuah nilai.

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

Apa gunanya ini? Tidak banyak, karena ini bukan cross-browser. Paling-paling, mungkin sedikit ketenangan pikiran yang setidaknya beberapa browser tidak akan membiarkan bookmarklet atau skrip pihak ketiga memodifikasi nilainya.

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

Pengembang web
sumber
1
Sukai kode itu! Jelek sih, tapi tes yang bagus untuk dukungan const. =)
Stein G. Strindhaug
1
agak lucu, ey - berapa banyak baris yang bisa Anda ketik untuk mendeklarasikan const?
Lebih cepat
4

Jika layak disebutkan, Anda bisa mendefinisikan konstanta dalam penggunaan sudut$provide.constant()

angularApp.constant('YOUR_CONSTANT', 'value');
Muhammad Reda
sumber
... dan Anda dapat menggunakan const di VBA ... xbrowser? ... ups ...;)
Lebih cepat
OP bertanya tentang javascript, menjawab penawaran dengan kerangka kerja JS yang sangat beralasan. Praktis di luar topik.
rounce
2
@rounce: Jawaban di luar topik masih merupakan jawaban, jangan tandai sebagai Bukan Jawaban, tetapi turunkan suara dan pilih untuk menghapus . Lihat Bagaimana cara saya menggunakan bendera "Bukan Jawaban" dengan benar?
Kevin Guan
@KevinGuan Tercatat, akan dilakukan di masa depan.
rounce
4

Sebuah versi perbaikan dari jawaban Burke yang memungkinkan Anda melakukan CONFIG.MY_CONSTbukan CONFIG.get('MY_CONST').

Ini membutuhkan IE9 + atau browser web nyata.

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

* Properti hanya baca, hanya jika nilai awal tidak berubah.

Şafak Gür
sumber
4

JavaScript ES6 (kembali) memperkenalkan constkata kunci yang didukung di semua browser utama .

Variabel yang dideklarasikan melalui consttidak dapat dideklarasikan ulang atau ditugaskan kembali.

Selain itu, constberperilaku mirip denganlet .

Itu berperilaku seperti yang diharapkan untuk tipe data primitif (Boolean, Null, Undefined, Number, String, Symbol):

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

Perhatian: Waspadai perangkap tentang objek:

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

Jika Anda benar-benar membutuhkan objek yang tidak berubah dan benar-benar konstan: Gunakan saja const ALL_CAPSuntuk memperjelas niat Anda. Ini adalah konvensi yang baik untuk diikuti untuk semua constdeklarasi, jadi andalkan saja.

le_m
sumber
Dari IE11 saja :-(
Mo.
3

Alternatif lain adalah sesuatu seperti:

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

Maka cukup: var foo = constantMap.MY_CONSTANT

Jika Anda melakukannya constantMap.MY_CONSTANT = "bar"tidak akan berpengaruh karena kami mencoba menggunakan operator penugasan dengan pengambil, maka itu constantMap.MY_CONSTANT === "myconstant"akan tetap benar.

mengaum
sumber
3

di Javascript sudah ada konstanta . Anda mendefinisikan konstanta seperti ini:

const name1 = value;

Ini tidak dapat diubah melalui penugasan kembali.

Erik Lucio
sumber
Per tautan dalam jawaban, ini adalah fitur eksperimental dan harus digunakan dengan hati-hati.
Johnie Karr
Tentu saja saya setuju dengan Anda. Tetapi dalam versi terakhir browser berfungsi.
Erik Lucio
3

Kata kunci 'const' telah diusulkan sebelumnya dan sekarang telah secara resmi dimasukkan dalam ES6. Dengan menggunakan kata kunci const, Anda dapat meneruskan nilai / string yang akan bertindak sebagai string yang tidak dapat diubah.

Ritumoni Sharma
sumber
2

Memperkenalkan konstanta ke dalam JavaScript paling-paling merupakan peretasan.

Cara yang bagus untuk membuat nilai yang persisten dan dapat diakses secara global dalam JavaScript adalah mendeklarasikan objek literal dengan beberapa properti "baca-saja" seperti ini:

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

Anda akan memiliki semua konstanta Anda dikelompokkan dalam satu objek aksesori "saya" di mana Anda dapat mencari nilai yang tersimpan atau apa pun yang mungkin telah Anda putuskan untuk dimasukkan ke sana. Sekarang mari kita coba apakah itu berfungsi:

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

Seperti yang bisa kita lihat, properti "my.constant1" telah mempertahankan nilai aslinya. Anda telah membuat sendiri beberapa konstanta sementara 'hijau' yang bagus ...

Tetapi tentu saja ini hanya akan melindungi Anda dari memodifikasi, mengubah, membatalkan, atau mengosongkan nilai konstan properti Anda secara tidak sengaja dengan akses langsung seperti dalam contoh yang diberikan.

Kalau tidak, saya masih berpikir bahwa konstanta adalah untuk boneka. Dan saya masih berpikir bahwa menukar kebebasan besar Anda dengan sudut keamanan yang menipu adalah perdagangan terburuk yang mungkin terjadi.

Bill the Lizard
sumber
2

Rhino.jsmengimplementasikan constselain apa yang disebutkan di atas.

isomorfisma
sumber