Có hằng số trong JavaScript không?


1132

Có cách nào để sử dụng hằng trong JavaScript không?

Nếu không, thực tế phổ biến để chỉ định các biến được sử dụng là hằng số là gì?


35
Chromecho phép bạn sử dụng từ khóa constđể sử dụng hằng số. ví dụ const ASDF = "asdf". Tuy nhiên, vì constkhông tương thích với nhiều trình duyệt, tôi thường tuân theo một vartuyên bố.
Jacksonkr

20
try{const thing=1091;}catch(e){var thing=1091;}làm.
Derek 朕 會

13
Derek: không phải thử / bắt của bạn sẽ giới hạn phạm vi của điều bạn đang khai báo cho khối thử / bắt? Nếu bạn không xác định đúng phạm vi thì điểm xác định consthoặc vartất cả là gì?
Bộ giải mã

8
@Coderer trong các triển khai hiện tại, điều này sẽ hoạt động, constcó cùng phạm vi với var, và đó là cấp độ chức năng, không phải cấp độ khối. Thay vào đó, nếu bạn tuân theo tiêu chuẩn ECMAScript sắp tới, constcó cùng phạm vi let, điều đó có nghĩa là nó sẽ không hoạt động.
Jasper

3
@Coderer Ngôn ngữ sai. Các biến trong javascript là phạm vi chức năng. Đây không phải là C.
doug65536

Câu trả lời:


1018

Kể từ ES2015 , JavaScript có một khái niệm về const:

const MY_CONSTANT = "some-value";

Điều này sẽ hoạt động trong hầu hết các trình duyệt trừ IE 8, 9 và 10 . Một số cũng có thể cần chế độ nghiêm ngặt được kích hoạt.

Bạn có thể sử dụng varvới các quy ước như ALL_CAPS để chỉ ra rằng các giá trị nhất định không nên được sửa đổi nếu bạn cần hỗ trợ các trình duyệt cũ hơn hoặc đang làm việc với mã kế thừa:

var MY_CONSTANT = "some-value";

60
Làm thế nào về const x = 24;
Zachary Scott

93
Lưu ý rằng nếu bạn không cần khả năng tương thích trình duyệt chéo (hoặc bạn đang lập trình phía máy chủ trong Rhino hoặc Node.js), bạn có thể sử dụng consttừ khóa. Hiện tại nó được hỗ trợ bởi tất cả các trình duyệt hiện đại trừ IE.
Husky

17
Những ngày này (3,5 năm sau), bạn có thể sử dụng Object.definePropertyđể tạo các thuộc tính chỉ đọc mà cũng không thể xóa được. Điều này hoạt động trong phiên bản hiện tại của tất cả các trình duyệt chính (nhưng không chính xác trong IE8 ). Xem câu trả lời của @NotAName
Phrogz

12
@Amyth Điều đó không thực sự hữu ích. Đó là một hướng dẫn phong cách được đề xuất bởi một nhà cung cấp duy nhất. Theo quan điểm của Husky ở trên, khả năng tương thích IE hoàn toàn không liên quan khi viết JS phía máy chủ.
aendrew

32
Vì câu trả lời này vẫn được Google xếp hạng cao trong năm 2015, nên có thể nói rằng nó đã lỗi thời. Các consttừ khóa chính thức tại là một phần của ngôn ngữ và được hỗ trợ bởi tất cả các trình duyệt. Theo statcount.com, chỉ một vài phần trăm người dùng internet vẫn sử dụng các phiên bản trình duyệt cũ không hỗ trợ const.
tristan

310

Bạn đang cố gắng bảo vệ các biến chống lại sửa đổi? Nếu vậy, thì bạn có thể sử dụng một mô-đun mô-đun:

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

Sử dụng phương pháp này, các giá trị không thể được sửa đổi. Nhưng, bạn phải sử dụng phương thức get () trên CONFIG :(.

Nếu bạn không cần bảo vệ nghiêm ngặt các giá trị của biến, thì chỉ cần thực hiện theo đề xuất và sử dụng quy ước TẤT CẢ CAPS.


13
Lưu ý rằng bạn chỉ có thể trả về một hàm cho giá trị của CONFIG. Điều đó sẽ giúp bạn tiết kiệm khi gọi CONFIG.get () mọi lúc.
Mathew Byrne

4
Giải pháp khá. Nhưng những thứ như vậy nên được gói gọn như một thư viện để không phát minh lại chúng trong bất kỳ dự án mới nào.
andrii

82
CONFIG.get = someNewFunctionThatBreaksTheCode... Nói chung, bạn hoàn toàn không thể thực thi các hằng số trong JS (từ khóa const / o const). Chỉ về điều duy nhất bạn có thể làm là hạn chế tầm nhìn.
Thomas Eding

28
Tôi tin rằng đó privatelà một từ dành riêng trong tương lai trong JavaScript, tôi sẽ không sử dụng nó nếu tôi là bạn.
Zaq

Đây cũng là mẫu đăng ký.

122

Các consttừ khóa nằm trong dự thảo ECMAScript 6 nhưng nó vậy, đến nay chỉ được hưởng một ít hỗ trợ trình duyệt: http://kangax.github.io/compat-table/es6/ . Cú pháp là:

const CONSTANT_NAME = 0;

13
Nếu bạn cố gắng gán giá trị cho a const, nó sẽ không gây ra bất kỳ lỗi nào. Việc gán chỉ thất bại và hằng số vẫn có giá trị ban đầu. Đây là một lỗ hổng thiết kế lớn IMHO nhưng miễn là có một quy ước đặt tên rõ ràng, nhất quán (như ALL_CAPS phổ biến) Tôi không nghĩ rằng nó sẽ gây ra quá nhiều đau buồn.
MatrixFrog

6
Hãy theo dõi hỗ trợ trình duyệt tại đây: kangax.github.io/es5-compat-table/es6/#const
Mark McDonald

6
Việc gán @MatrixFrog sẽ gây ra lỗi với 'use strict'.
sam

Tôi có nên xác định hằng số trong ALL CAPS?
Lewis

1
@Tresdin Đó là một quy ước đặt tên phổ biến để xác định các hằng số trong tất cả các mũ. Không có gì trong thông số kỹ thuật buộc nó, nhưng đó không phải là một ý tưởng tồi. Nó làm cho nó rõ ràng hơn ý định của bạn là gì, vì vậy nó cải thiện khả năng đọc mã.
Bill 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

Xem Object.freeze . Bạn có thể sử dụngconst nếu bạn muốn làm cho constantschỉ đọc tham chiếu.


2
Nên đề cập đến điều này chỉ hoạt động trên IE9 + kangax.github.io/compat-table/es5 .
Cordle

Tôi sẽ, nếu nó không có sự triển khai bị phá vỡi
Alnitak

Lưu ý: điều này hoạt động tương tự như constkhai báo ES6 , ví dụ các thuộc tính không thể được khai báo lại hoặc gán lại, nhưng nếu chúng là kiểu dữ liệu object, chúng có thể bị thay đổi.
le_m

Chính xác những gì tôi đang tìm kiếm. Bạn cũng có thể sử dụng const constantsthay vì var constantsđể ngăn chặn biến được gán lại.
Jarett Millard

Xem, ví dụ, đóng băng sâu cho đóng băng đệ quy.
sam

64

IE không hỗ trợ các hằng, loại, ví dụ:

<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
Boy, nói về một cái gì đó không phải là trình duyệt chéo. . . Vẫn +1 vì suy nghĩ một chút ngoài hộp.
Tom

14
VBScript? Cái gì vậy ;)
tybro0103

2
Tôi thường bỏ phiếu cho câu hỏi trình duyệt chéo có liên quan chung, với câu trả lời cụ thể về IE. Vì tôi ghét những người nghĩ rằng việc triển khai javascript của IE là "Một" và những người khác chỉ bị bỏ qua. Ai đang sử dụng các borws khác ngoài IE, btw?
Kiến

@Cooluhuru tập lệnh này xuất hiện để xử lý cả trình duyệt IE (sử dụng VBScript) và trình duyệt không IE (sử dụng JavaScript const). Bạn có thể giải thích những gì sai với nó?
Andrew Grimm

Tôi vẫn có một thời gian khó chấp nhận rằng hằng số có thể được thay đổi.
Norbert Norbertson

59

ECMAScript 5 giới thiệu Object.defineProperty:

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

được hỗ trợ trong mọi trình duyệt hiện đại (cũng như IE 9).

Xem thêm: Object.defineProperty trong ES5?


1
Điều đáng chú ý là đây không giống như một hằng số truyền thống. Điều này sẽ chỉ cho phép bạn xác định một thuộc tính không đổi (của một đối tượng không cố định). Ngoài ra, điều này không tạo ra lỗi và thậm chí trả về giá trị bạn cố gắng đặt. Nó chỉ đơn giản là không viết giá trị.
Cory Gross

3
Gần đây tôi đã đọc rằng cố gắng gán cho một thuộc tính writable: false sẽ thực sự gây ra lỗi nếu mã thực hiện chuyển nhượng đang được diễn giải theo chế độ nghiêm ngặt của ECMAScript 5. Chỉ cần một lý do khác để viết 'use strict'vào mã của bạn.
Cory Gross

6
Bạn thực sự có thể bỏ qua writable: falsevì đó là mặc định .
sam

24

Không, không nói chung. Firefox thực hiện constnhưng tôi biết IE không.


@ John chỉ ra một cách đặt tên phổ biến cho các const đã được sử dụng trong nhiều năm bằng các ngôn ngữ khác, tôi thấy không có lý do gì bạn không thể sử dụng nó. Tất nhiên điều đó không có nghĩa là ai đó sẽ không viết lên giá trị của biến. :)


11
Như mọi người đều biết, nếu IE không thực hiện nó, nó cũng có thể không tồn tại.
Josh Hinman

3
Thật không may, và thực tế nói - đó là sự thật. IE sở hữu một thị phần rất lớn trên thị trường. Nếu tôi sở hữu một doanh nghiệp và có các ứng dụng web được sử dụng nội bộ, tôi sẽ chuẩn hóa FF. Tôi không biết tại sao rất nhiều người quan tâm đến IE, nó thổi.
Jason Bunting

@Rich: Ai nói ý kiến ​​của tôi là sự thật? Bạn đã thực hiện khá giả định. Bên cạnh đó, theo như tôi nghĩ, thực tế là IE tệ là một sự thật. Bạn có thể có sự thật của riêng bạn, tôi không nói bạn phải tin tôi. : P Lấy Xanax hoặc thứ gì đó ...
Jason Bunting

@Rich B, yea đó chỉ là một bình luận ngu ngốc để làm, và tin tưởng tôi, tôi sẽ biết, tôi đưa ra nhiều bình luận ngu ngốc. @Jason B. - thật thú vị, tôi đã gặp phải vấn đề rất lớn đêm qua .. const làm việc trong FF nhưng không phải IE. Cảm ơn đã làm rõ

Ai quan tâm đến IE? Tôi không! FF hoặc Chrome hoặc Opera, v.v ... có thể được cài đặt gần như trong mọi nền tảng HĐH. Ngoài ra các nhà bán lẻ máy tính thường biết phiên bản IE cũ hút nên họ thường (hoặc thậm chí mọi lúc) cài đặt các trình duyệt thay thế trước khi bán máy tính. Vì vậy, tôi đã quyết định cho ứng dụng đã phát triển của mình không quan tâm đến tất cả các trình duyệt không tương thích: nếu các nhà phát triển trình duyệt quan tâm đến việc tôn trọng các tiêu chuẩn, sản phẩm của họ có thể sử dụng ứng dụng của tôi, nếu không, người dùng sẽ sử dụng một trình duyệt khác ... Tôi có thể sống với nó; -) Nhưng Microsoft có thể mất một phần thị trường không? Không, họ không thể "Họ" sẽ thay đổi chính trị dev của họ!
willy wonka

20

Trong JavaScript, sở thích của tôi là sử dụng các hàm để trả về các giá trị không đổi.

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


alert(MY_CONSTANT());

6
Đáng để chỉ ra rằng điều này rơi vào cùng một vấn đề được đề cập trong câu trả lời của @Burkes (bình luận của @trinithis). `MY_CONSTANT = function () {trả về" some-other-value "; } phá vỡ nó. +1 mặc dù, giải pháp tốt và nhanh chóng.
Patrick M

13
-1. Điều này không có lợi ích gì so với var SOME_NAME = value (nó vẫn có thể thay đổi), có nhiều mã hơn và yêu cầu giải thích.
mikemaccana

@PatrickM trong khi sự thật là bạn có thể sửa đổi loại hằng giả đó, bằng các ngôn ngữ khác như C, mà bạn không thể sửa đổi các hằng số, bạn vẫn có thể thực hiện thông qua con trỏ. Vì vậy, miễn là bạn sử dụng một số phương pháp mà ít nhất gợi ý rằng đó là một hằng số, thì nó vẫn ổn.
rev

20

Mozillas MDN Web Docs chứa các ví dụ và giải thích hay về const. Trích đoạn:

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

Nhưng thật đáng buồn khi IE9 / 10 vẫn không hỗ trợ const. Và lý do nó vô lý :

Vậy, IE9 đang làm gì với const? Cho đến nay, quyết định của chúng tôi là không hỗ trợ nó. Nó chưa phải là một tính năng đồng thuận vì nó chưa bao giờ có sẵn trên tất cả các trình duyệt.

...

Cuối cùng, có vẻ như giải pháp lâu dài tốt nhất cho web là loại bỏ nó và chờ các quy trình tiêu chuẩn hóa để chạy khóa học của họ.

Họ không thực hiện nó vì các trình duyệt khác đã không thực hiện đúng?! Quá sợ làm cho nó tốt hơn? Định nghĩa tiêu chuẩn hay không, một hằng số là một hằng số: đặt một lần, không bao giờ thay đổi.

Và với tất cả các ý tưởng: Mọi chức năng đều có thể được ghi đè (XSS, v.v.). Vì vậy, không có sự khác biệt trong varhoặc function(){return}.constlà hằng số thực duy nhất.

Cập nhật: IE11 hỗ trợ const :

IE11 bao gồm hỗ trợ cho các tính năng được xác định rõ và thường được sử dụng trong những tiêu chuẩn ECMAScript 6 mới nổi bao gồm let, const, Map, Set, và WeakMap, cũng như __proto__để cải thiện khả năng tương tác.


25
"Nó chưa bao giờ có sẵn trên tất cả các trình duyệt". Nếu bạn không làm cho nó có sẵn trong IE thì nó sẽ không bao giờ có trong tất cả các trình duyệt.
km1

lái xe tiêu chuẩn hóa không phải dành cho tất cả mọi người;) - các công ty đến và họ lại đi - cảm ơn bạn đã trích dẫn tỷ lệ cược trong gỗ
Nhanh hơn

thêm một điều nữa về điều này: VBA chưa phải là một tính năng liên quan trong tất cả các trình duyệt và MS hỗ trợ const trong VBA - đây là quyền làm chủ ngân sách phát triển kênh;)
Nhanh hơn

17

Nếu bạn không phiền khi sử dụng các chức năng:

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

Cách tiếp cận này cung cấp cho bạn các hàm thay vì các biến thông thường, nhưng nó đảm bảo * rằng không ai có thể thay đổi giá trị một khi nó được đặt.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Cá nhân tôi thấy điều này khá dễ chịu, đặc biệt sau khi đã quen với mô hình này từ các vật quan sát loại trực tiếp.

* Trừ khi ai đó xác định lại chức năng constanttrước khi bạn gọi nó


1
underscore.js thực hiện một hàm hằng giống hệt mã này.
Thượng lưu

Đơn giản, súc tích và trả lời đúng tinh thần của câu hỏi của OP. Điều này sẽ nhận được nhiều upVote hơn.
Mac

3
Điều này không bao giờ thực sự làm việc cho tôi. Mặc dù việc đóng cửa làm cho nó không thay đổi, var bạn gán nó vẫn có thể bị ghi đè. Ví dụ: a = constant(10); a(10); // 10theo sau a = constant(25); a(); //25, không có lỗi hoặc cảnh báo nào được đưa ra, không có dấu hiệu cho thấy hằng số của bạn đã bị phá vỡ.
Patrick M

Nếu tôi gán lại giá trị cho anó thì nó sẽ thay đổi thành giá trị mới
Saurabh Sharma

17

với api Object "mới", bạn có thể làm một cái gì đó như thế này:

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

hãy xem điều này trên Mozilla MDN để biết thêm chi tiết. Đây không phải là biến cấp đầu tiên, vì nó được gắn vào một đối tượng, nhưng nếu bạn có phạm vi, bất cứ điều gì, bạn có thể gắn nó vào đó. thisnên làm việc như là tốt. Vì vậy, ví dụ thực hiện điều này trong phạm vi toàn cầu sẽ khai báo giá trị giả không đổi trên cửa sổ (đây là một ý tưởng thực sự tồi tệ, bạn không nên tuyên bố các vars toàn cầu một cách bất cẩn)

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

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

lưu ý: gán sẽ trả lại cho bạn giá trị được gán trong bảng điều khiển, nhưng giá trị của biến sẽ không thay đổi


Không hoạt động trong safari và trong mozilla nếu bạn thực hiện lại câu lệnh xác định - với một giá trị khác - nó sẽ gán lại giá trị.
Akshay

2
Không "không làm việc trong safari", không được hỗ trợ trong safari. Không giống nhau. Và nó sẽ ném một 'Uncaught TypeError: Không thể xác định lại thuộc tính: <tên thuộc tính ở đây>' nếu bạn thử điều đó. hoặc bạn đang làm sai, hoặc ff của bạn thực hiện nó không đúng. Tôi đoán đó là sự pha trộn của cả hai.
chục

14

Nhóm hằng số thành các cấu trúc nếu có thể:

Ví dụ, trong dự án trò chơi hiện tại của tôi, tôi đã sử dụng dưới đây:

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

Bài tập:

var wildType = CONST_WILD_TYPES.REGULAR;

So sánh:

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

Gần đây tôi đang sử dụng, để so sánh:

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

IE11 với tiêu chuẩn ES6 mới có khai báo 'const'.
Ở trên hoạt động trong các trình duyệt trước đó như IE8, IE9 & IE10.


12

Bạn có thể dễ dàng trang bị cho tập lệnh của mình một cơ chế cho các hằng số có thể được đặt nhưng không bị thay đổi. Một nỗ lực để thay đổi chúng sẽ tạo ra một lỗi.

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

Quên IE và sử dụng consttừ khóa.


9
làm việc cho tôi nhưng sau đó tôi đang viết một tiện ích mở rộng chrome, vì vậy tôi biết tôi đang sử dụng trình duyệt lành mạnh ...
yoyo

1
@yoyo phần hay nhất về cách viết tiện ích mở rộng và addons - không hỗ trợ trình duyệt chéo!
Ian

1
@Ian Chào mừng đến năm 2019, sự không thống nhất giữa các trình duyệt đã gần như biến mất :)
Fusseldieb

9

Tuy nhiên, không có trình duyệt chéo chính xác được xác định trước để làm điều đó, bạn có thể đạt được nó bằng cách kiểm soát phạm vi của các biến như thể hiện trên các câu trả lời khác.

Nhưng tôi sẽ đề nghị sử dụng không gian tên để phân biệt với các biến khác. điều này sẽ làm giảm cơ hội va chạm đến mức tối thiểu từ các biến khác.

Đặt tên đúng như

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

vì vậy trong khi sử dụng nó sẽ iw_constant.namehoặciw_constant.age

Bạn cũng có thể chặn thêm bất kỳ khóa mới hoặc thay đổi bất kỳ khóa nào bên trong iw_constant bằng phương thức Object.freeze. Tuy nhiên, nó không được hỗ trợ trên trình duyệt cũ.

Ví dụ:

Object.freeze(iw_constant);

Đối với trình duyệt cũ hơn, bạn có thể sử dụng polyfill cho phương thức đóng băng.


Nếu bạn ổn với chức năng gọi sau đây là cách tốt nhất để xác định hằng số. Phân tích đối tượng của bạn trong một hàm tự thực thi và trả về hàm get cho các hằng số của bạn, ví dụ:

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

       };

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

// để có được giá trị sử dụng iw_constant('name') hoặciw_constant('age')


** Trong cả hai ví dụ, bạn phải rất cẩn thận về khoảng cách tên để không thể thay thế đối tượng hoặc chức năng của bạn thông qua thư viện khác. (Nếu đối tượng hoặc chức năng sẽ bị thay thế, toàn bộ hằng số của bạn sẽ biến mất)


7

Trong một thời gian, tôi đã chỉ định "hằng số" (vẫn chưa thực sự là hằng số) trong các đối tượng được truyền qua các with()câu lệnh. Tôi nghĩ rằng nó rất thông minh. Đây là một ví dụ:

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

Trong quá khứ, tôi cũng đã tạo một CONSTkhông gian tên nơi tôi sẽ đặt tất cả các hằng số của mình. Một lần nữa, với chi phí chung. Sheesh.

Bây giờ, tôi chỉ làm var MY_CONST = 'whatever';để HÔN .


16
Nếu có gì đó ác hơn eval, thì chắc chắn with.
NikiC

4
eval là rất xấu xa! Nó bị cháy nhà tôi một lần!
W3Geek

6

Ý kiến ​​của tôi (chỉ hoạt động với các đối tượng).

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

Thử! Nhưng hiểu - đây là đối tượng, nhưng không phải là biến đơn giản.

Hãy thử chỉ:

const a = 9;

5

Tôi cũng đã có một vấn đề với điều này. Và sau một thời gian tìm kiếm câu trả lời và xem xét tất cả các câu trả lời của mọi người, tôi nghĩ rằng tôi đã đưa ra một giải pháp khả thi cho vấn đề này.

Có vẻ như hầu hết các câu trả lời mà tôi đã gặp đều sử dụng các hàm để giữ các hằng số. Như nhiều người dùng của NHIỀU diễn đàn đăng bài, các chức năng có thể dễ dàng được viết bởi người dùng ở phía máy khách. Tôi bị thu hút bởi câu trả lời của Keith Evetts rằng đối tượng hằng số không thể được truy cập từ bên ngoài, mà chỉ từ các chức năng bên trong.

Vì vậy, tôi đã đưa ra giải pháp này:

Đặt mọi thứ bên trong một hàm ẩn danh để theo cách đó, các biến, đối tượng, v.v. không thể được thay đổi bởi phía máy khách. Đồng thời ẩn các chức năng 'thực' bằng cách các chức năng khác gọi các chức năng 'thực' từ bên trong. Tôi cũng đã nghĩ đến việc sử dụng các hàm để kiểm tra xem một hàm đã bị thay đổi bởi người dùng ở phía máy khách chưa. Nếu các chức năng đã được thay đổi, hãy thay đổi chúng trở lại bằng các biến được 'bảo vệ' ở bên trong và không thể thay đổi.

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

Dường như bảo mật thực sự là một vấn đề và không có cách nào để 'ẩn' bạn lập trình khỏi phía khách hàng. Một ý tưởng tốt cho tôi là nén mã của bạn để mọi người, kể cả bạn, lập trình viên, đọc và hiểu nó thực sự khó khăn. Có một trang web bạn có thể truy cập: http://javascriptcompressor.com/ . (Đây không phải là trang web của tôi, đừng lo lắng tôi không quảng cáo.) Đây là trang web sẽ cho phép bạn nén và làm xáo trộn mã Javascript miễn phí.

  1. Sao chép tất cả các mã trong tập lệnh trên và dán nó vào văn bản hàng đầu trên trang javascriptcompressor.com.
  2. Kiểm tra hộp kiểm mã hóa Base62, chọn hộp kiểm Shrink Biến.
  3. Nhấn nút Nén.
  4. Dán và lưu tất cả trong tệp .js và thêm nó vào trang của bạn ở đầu trang.

Đây là một giải pháp tốt có thể được bao bọc độc đáo như một thư viện để bao gồm. Nhưng tôi không thích việc đặt tên các biến của bạn trong mã này. Tại sao bỏ các tên mô tả như "tên" và "giá trị" như được sử dụng trong mã của Keith? Vấn đề nhỏ, nhưng vẫn còn.
Cordle

5

Rõ ràng điều này cho thấy sự cần thiết của một từ khóa const trình duyệt chéo được tiêu chuẩn hóa.

Nhưng bây giờ:

var myconst = value;

hoặc là

Object['myconst'] = value;

Cả hai dường như đủ và bất cứ điều gì khác giống như bắn một con ruồi bằng bazooka.


lấy var myconst = value cũ tốt; và để gỡ lỗi, hãy sử dụng mã gỡ lỗi bổ sung ... - hoạt động như điên miễn là không phải tất cả các trình duyệt đều hỗ trợ const
Quicker

4

Tôi sử dụng constthay vì vartrong các tập lệnh Greasemonkey của mình, nhưng đó là bởi vì chúng sẽ chỉ chạy trên Firefox ...
Quy ước tên có thể thực sự là cách để đi (tôi cũng làm cả hai!).


4

Trong JavaScript, thực tế của tôi là tránh các hằng số nhiều nhất có thể và sử dụng các chuỗi thay thế. Các vấn đề với hằng số xuất hiện khi bạn muốn đưa các hằng số của mình ra thế giới bên ngoài:

Ví dụ: người ta có thể triển khai API ngày sau:

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

Nhưng nó ngắn hơn nhiều và tự nhiên hơn để viết đơn giản:

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

Cách này "ngày" và "giờ" thực sự hoạt động như các hằng số, bởi vì bạn không thể thay đổi từ bên ngoài bao nhiêu giây "giờ" thể hiện. Nhưng nó dễ dàng ghi đè lên MyModule.Date.HOUR.

Cách tiếp cận này cũng sẽ hỗ trợ gỡ lỗi. Nếu Fireorms nói với bạn action === 18, thật khó để hiểu ý nghĩa của nó, nhưng khi bạn nhìn thấy action === "save"thì nó lập tức rõ ràng.


Thật không may là khá dễ mắc lỗi chính tả - ví dụ "Hours"thay vì "hours"- nhưng một IDE có thể cho bạn biết sớm về điều đó Date.Hourskhông được xác định.
le_m

4

Được rồi, điều này thật xấu, nhưng nó mang lại cho tôi một hằng số trong Firefox và Chromium, một hằng số bất biến (WTF?) Trong Safari và Opera và một biến trong IE.

Tất nhiên eval () là xấu, nhưng không có nó, IE đưa ra một lỗi, ngăn các tập lệnh chạy.

Safari và Opera hỗ trợ từ khóa const, nhưng bạn có thể thay đổi giá trị của const .

Trong ví dụ này, mã phía máy chủ đang viết JavaScript vào trang, thay thế {0} bằng một giá trị.

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

Cái này tốt cho cái gì? Không nhiều, vì nó không phải là trình duyệt chéo. Tốt nhất, có thể yên tâm một chút rằng ít nhất là một số trình duyệt sẽ không để bookmarklets hoặc tập lệnh của bên thứ ba sửa đổi giá trị.

Đã thử nghiệm với Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9.


1
Yêu mã đó! Xấu xí như quái, nhưng một bài kiểm tra tốt cho hỗ trợ const. =)
Stein G. Strindhaug

1
hơi buồn cười, bạn có thể gõ bao nhiêu dòng để khai báo một const?
Nhanh hơn

4

Nếu nó đáng được đề cập, bạn có thể định nghĩa các hằng số trong góc bằng cách sử dụng$provide.constant()

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

... và bạn có thể sử dụng const trong VBA ... xbrowser? ... up ...;)
Nhanh hơn

OP hỏi về javascript, trả lời các giao dịch với khung JS được đánh giá cao cụ thể. Thực tế lạc đề.
tung lên

2
@rounce: Off-chủ đề câu trả lời vẫn là câu trả lời, đừng cờ chúng như Không một câu trả lời nhưng downvotebỏ phiếu để xóa để thay thế. Xem Làm thế nào để tôi sử dụng đúng cách Không phải là cờ Trả lời?
Kevin Guan

@KevinGuan Lưu ý, sẽ làm trong tương lai.
tung lên

4

Một phiên bản cải tiến của câu trả lời của Burke cho phép bạn làm CONFIG.MY_CONSTthay vì CONFIG.get('MY_CONST').

Nó đòi hỏi IE9 + hoặc một trình duyệt web thực sự.

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

* Các thuộc tính là chỉ đọc, chỉ khi các giá trị ban đầu là bất biến.


4

JavaScript ES6 (lại) đã giới thiệu consttừ khóa được hỗ trợ trong tất cả các trình duyệt chính .

Các biến được khai báo thông qua constkhông thể được khai báo lại hoặc gán lại.

Ngoài ra, consthành vi tương tự như let.

Nó hoạt động như mong đợi cho các kiểu dữ liệu nguyên thủy (Boolean, Null, Không xác định, Số, Chuỗi, Biểu tượng):

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

Chú ý: Hãy nhận biết những cạm bẫy liên quan đến các đối tượng:

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

Nếu bạn thực sự cần một đối tượng bất biến và hoàn toàn không đổi: Chỉ cần sử dụng const ALL_CAPSđể làm rõ ý định của bạn. Dù sao đó cũng là một quy ước tốt để tuân theo tất cả các consttuyên bố, vì vậy chỉ cần dựa vào nó.


Chỉ từ IE11 :-(
Mo.

3

Một cách khác là một cái gì đó như:

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

Sau đó, đơn giản là: var foo = constantMap.MY_CONSTANT

Nếu bạn đã làm constantMap.MY_CONSTANT = "bar"điều đó sẽ không có tác dụng gì vì chúng tôi đang cố gắng sử dụng một toán tử gán với một getter, do đó constantMap.MY_CONSTANT === "myconstant"sẽ vẫn đúng.


3

trong Javascript đã tồn tại hằng . Bạn định nghĩa một hằng số như thế này:

const name1 = value;

Điều này không thể thay đổi thông qua việc gán lại.


Theo liên kết trong câu trả lời, đây là một tính năng thử nghiệm và nên được sử dụng một cách thận trọng.
Johnie Karr

Tất nhiên, tôi đồng ý với bạn. Nhưng trong các phiên bản cuối cùng của trình duyệt Nó hoạt động.
Erik Lucio

3

Từ khóa 'const' đã được đề xuất trước đó và bây giờ nó đã được chính thức đưa vào ES6. Bằng cách sử dụng từ khóa const, bạn có thể truyền một giá trị / chuỗi sẽ hoạt động như một chuỗi bất biến.


2

Giới thiệu các hằng số vào JavaScript là tốt nhất là một hack.

Một cách hay để tạo các giá trị liên tục và có thể truy cập toàn cầu trong JavaScript sẽ là khai báo một đối tượng bằng chữ với một số thuộc tính "chỉ đọc" như thế này:

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

bạn sẽ có tất cả các hằng số của bạn được nhóm trong một đối tượng phụ kiện "của tôi" nơi bạn có thể tìm kiếm các giá trị được lưu trữ của mình hoặc bất kỳ thứ gì khác mà bạn có thể đã quyết định đặt ở đó cho vấn đề đó. Bây giờ hãy kiểm tra nếu nó hoạt động:

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

Như chúng ta có thể thấy, thuộc tính "my.constant1" đã giữ nguyên giá trị ban đầu của nó. Bạn đã tạo cho mình một số hằng số tạm thời "xanh" đẹp ...

Nhưng tất nhiên, điều này sẽ chỉ bảo vệ bạn khỏi việc vô tình sửa đổi, thay đổi, vô hiệu hóa hoặc làm trống giá trị hằng số thuộc tính của bạn với một truy cập trực tiếp như trong ví dụ đã cho.

Nếu không, tôi vẫn nghĩ rằng hằng số là dành cho người giả. Và tôi vẫn nghĩ rằng trao đổi tự do tuyệt vời của bạn cho một góc nhỏ của an ninh lừa đảo là giao dịch tồi tệ nhất có thể.


2

Rhino.jsthực hiện constngoài những gì đã được đề cập ở trên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.