JavaScript에는 상수가 있습니까?


1132

JavaScript 에서 상수를 사용하는 방법이 있습니까?

그렇지 않은 경우 상수로 사용되는 변수를 지정하는 일반적인 방법은 무엇입니까?


35
Chromeconst상수를 사용 하기 위해 키워드 를 사용할 수 있습니다. 예 const ASDF = "asdf". 그러나 const다중 브라우저와 호환되지 않으므로 일반적으로 var선언을 고수합니다 .
Jacksonkr

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

13
Derek : try / catch가 try / catch 블록으로 선언하는 범위를 제한하지 않습니까? 당신이 제대로 범위를 정하지 const않으면 지정의 요점은 무엇 var입니까?
Coderer

8
현재 구현에서 @Coderer는와 const동일한 범위를 가지며 작동하며 var블록 수준이 아닌 함수 수준입니다. 다가오는 ECMAScript 표준을 따르는 경우 const와 같은 범위를 가지므로 let작동하지 않습니다.
재스퍼

3
@Coderer 잘못된 언어입니다. 자바 스크립트의 변수는 함수 범위입니다. 이것은 C가 아닙니다.
doug65536

답변:


1018

ES2015 이후 JavaScript는 다음과 같은 개념을 가지고 있습니다 const.

const MY_CONSTANT = "some-value";

이것은 IE 8, 9 및 10을 제외한 거의 모든 브라우저 에서 작동 합니다. 일부는 엄격한 모드를 사용해야 할 수도 있습니다 .

varALL_CAPS와 같은 규칙을 사용 하여 이전 브라우저를 지원해야하거나 레거시 코드로 작업하는 경우 특정 값을 수정해서는 안됨을 표시 할 수 있습니다 .

var MY_CONSTANT = "some-value";

60
const x = 24는 어떻습니까?
Zachary Scott

93
브라우저 간 호환성이 필요하지 않은 경우 (또는 Rhino 또는 Node.js에서 서버 측 프로그래밍 인 경우) const키워드를 사용할 수 있습니다 . 현재 IE를 제외한 모든 최신 브라우저에서 지원됩니다.
Husky

17
요즘 (3.5 년 후) Object.defineProperty삭제할 수없는 읽기 전용 속성을 만드는 데 사용할 수 있습니다. 이것은 모든 주요 브라우저의 현재 버전에서 작동하지만 IE8 에서는 올바르지 않습니다 . @NotAName의 답변보기
Phrogz

12
@Amyth 그다지 도움이되지 않습니다. 단독 벤더가 제안한 스타일 가이드 입니다. 위의 Husky의 요점에 따르면 서버 측 JS를 작성할 때 IE 호환성은 전혀 관련이 없습니다.
aendrew

32
이 답변은 2015 년에도 Google에서 여전히 높은 순위를 차지하고 있으므로 이제는 더 이상 사용되지 않습니다. const키워드는 이제 언어의 공식적 일부이며 모든 브라우저에서 지원됩니다. statcounter.com에 따르면 인터넷 사용자의 일부만이 여전히 지원하지 않는 이전 브라우저 버전을 사용합니다 const.
tristan

310

변수가 수정되지 않도록 보호하려고합니까? 그렇다면 모듈 패턴을 사용할 수 있습니다.

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

이 방법을 사용하면 값을 수정할 수 없습니다. 그러나 CONFIG :(.)에서 get () 메소드를 사용해야합니다.

변수 값을 엄격하게 보호 할 필요가 없으면 제안 된대로 수행하고 모든 CAPS 규칙을 사용하십시오.


13
CONFIG 값에 대한 함수 만 반환 할 수 있습니다. CONFIG.get ()을 항상 호출하면 저장됩니다.
Mathew Byrne

4
예쁜 해결책. 그러나 그러한 것들을 새로운 프로젝트에서 다시 만들지 않도록 라이브러리로 포장해야합니다.
andrii

82
CONFIG.get = someNewFunctionThatBreaksTheCode... 대체로 JS (const 키워드가없는)에서 상수를 시행 할 수는 없습니다. 당신이 할 수있는 유일한 것은 가시성을 제한하는 것입니다.
Thomas Eding

28
나는 그것이 privateJavaScript의 미래 예약어 라고 생각 합니다. 내가 당신이라면 그것을 사용하지 않을 것입니다.
Zaq

레지스트리 패턴이기도합니다.

122

const키워드에 ECMA 스크립트 (6) 초안 하지만 지금까지 유일한 브라우저 지원의 겉 핥기 즐깁니다 : http://kangax.github.io/compat-table/es6/를 . 구문은 다음과 같습니다.

const CONSTANT_NAME = 0;

13
에 값을 할당하려고 const하면 오류가 발생하지 않습니다. 할당은 실패하고 상수는 여전히 원래 값을 갖습니다. 이것은 주요 디자인 결함 IMHO이지만 명확하고 일관된 이름 지정 규칙 (예 : 인기있는 ALL_CAPS)이있는 한 너무 슬픔을 일으킬 것이라고 생각하지 않습니다.
MatrixFrog

6
여기에 브라우저 지원에 눈을 유지 : kangax.github.io/es5-compat-table/es6/#const
마크 맥도날드에게

6
@MatrixFrog 대입으로 오류가 발생합니다 'use strict'.
sam

에 상수를 정의해야합니까 ALL CAPS?
Lewis

1
@Tresdin 모든 대문자로 상수를 정의하는 것은 일반적인 명명 규칙입니다. 언어 사양에 아무것도 강제하지 않지만 나쁜 생각은 아닙니다. 의도가 더 명확 해 지므로 코드 가독성이 향상됩니다.
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

Object.freeze를 참조하십시오 . 참조를 읽기 전용으로 만들려는 경우 사용할const 수 있습니다 constants.


2
이것은 IE9 + kangax.github.io/compat-table/es5 에서만 작동합니다 .
Cordle

만약 구현이 깨지지 않았다면i
Alnitak

참고 : 이것은 ES6 const선언 과 유사하게 작동합니다 . 예를 들어 속성을 다시 선언하거나 재 할당 object할 수 없지만 datatype 인 경우 변경 될 수 있습니다.
le_m 2016 년

정확히 내가 찾던 것. const constants대신 var constants변수를 다시 할당하지 않도록 대신 사용할 수도 있습니다 .
Jarett Millard

예를 들어 재귀 적 동결을 위한 급속 동결 을 참조하십시오 .
sam

64

IE는 다음과 같은 상수를 지원합니다.

<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
소년, 크로스 브라우저가 아닌 것에 대해 이야기하십시오. . . 상자 밖에서 조금 생각하면 여전히 +1입니다.
Tom

14
VBScript? 그게 뭐야? ;)
tybro0103

2
나는 일반적으로 IE 관련 답변과 함께 일반적인 크로스 브라우저 질문에 투표합니다. 나는 IE 자바 스크립트 구현이 'The One'이라고 생각하는 사람들을 싫어하고 다른 사람들은 무시해야합니다. IE 이외의 다른업자를 누가 사용하고 있습니까?
앤트

@Cooluhuru이 스크립트는 IE 브라우저 (VBScript 사용)와 비 IE 브라우저 (JavaScript 사용)를 모두 처리하는 것으로 보입니다 const. 무엇이 잘못되었는지 설명해 주실 수 있습니까?
Andrew Grimm

상수를 변경할 수 있다는 것을 받아들이는 데 여전히 어려움이 있습니다.
Norbert Norbertson

59

ECMAScript 5는 다음을 소개합니다 Object.defineProperty:

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

그것은있어 모든 현대적인 브라우저에서 지원 (물론 IE ≥ 9).

ES5의 Object.defineProperty 도 참조하십시오 .


1
이것이 전통적인 상수와는 다르다는 점에 주목할 가치가 있습니다. 이렇게하면 상수가 아닌 객체의 상수 속성 만 정의 할 수 있습니다. 또한 이것은 오류를 생성하지 않으며 설정하려는 값을 반환합니다. 단순히 가치를 쓰지 않습니다.
Cory Gross

3
최근에 할당을 수행하는 코드가 ECMAScript 5의 엄격 모드에서 해석되는 경우 속성에 할당을 시도 writable: false 하면 실제로 오류가 발생 한다는 것을 읽었습니다 . 'use strict'코드에 작성해야하는 또 다른 이유 입니다.
Cory Gross

6
writable: false이것이 기본값 이므로 실제로 생략 할 수 있습니다 .
sam

24

아니요, 일반적으로 아닙니다. Firefox는 구현 const하지만 IE는 그렇지 않습니다.


@ 존 다른 언어로 년 동안 사용되어왔다 consts에 대한 일반적인 명명 연습 점, 나는 당신이 그것을 사용할 수없는 이유가 없습니다. 물론 이것이 누군가가 변수의 값을 덮어 쓰지 않는다는 것을 의미하지는 않습니다. :)


11
모두가 알다시피 IE가 구현하지 않으면 존재하지 않을 수도 있습니다.
Josh Hinman

3
불행히도 실제로 말하면 사실입니다. IE는 시장에서 큰 비중을 차지하고 있습니다. 비즈니스를 소유하고 있고 웹 응용 프로그램을 내부적으로 사용한 경우 FF를 표준화합니다. 왜 많은 사람들이 IE에 관심을 가지는지 모르겠습니다.
Jason Bunting

@Rich : 누가 내 의견은 사실이라고 했습니까? 당신은 상당히 가정했습니다. 게다가, 내가 걱정하는 한, IE가 빨아 먹는 사실은 사실입니다. 당신은 당신의 자신의 사실을 가질 수 있습니다, 나는 당신이 내 것을 믿어야한다고 말하지 않았습니다. : P Xanax 또는 무언가를 가져 가라 ...
Jason Bunting

@Rich B, 예, 그것은 바보 같은 의견을 말하고 나를 믿습니다. 나는 많은 바보 같은 의견을 제시합니다. @Jason B.-흥미롭게도, 나는 지난 밤 에이 문제에 부딪 쳤습니다. 설명을 주셔서 감사합니다

누가 IE에 관심이 있습니까? 나는하지 않습니다! FF, Chrome 또는 Opera 등은 거의 모든 OS 플랫폼에 설치할 수 있습니다. 또한 컴퓨터 소매 업체는 일반적으로 이전 IE 버전이 빨라 컴퓨터를 판매하기 전에 대체 브라우저를 설치하는 경우가 종종 있습니다. 따라서 개발 된 앱이 호환되지 않는 브라우저를 전혀 신경 쓰지 않기로 결정했습니다. 브라우저 개발자가 표준을 존중하여 제품이 내 앱을 사용할 수 있다면 관심이 없다면 사용자는 다른 브라우저를 사용할 것입니다. -) 그러나 마이크로 소프트는 시장의 일부를 잃어 버릴 수 있습니까? "그들"은 그들의 개발 정치를 바꿀 수 없습니다!
willy wonka

20

JavaScript에서는 함수를 사용하여 상수 값을 반환하는 것이 좋습니다.

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


alert(MY_CONSTANT());

6
이것은 @Burkes answer (@trinithis 'comment)에서 언급 한 것과 동일한 문제에 속한다는 것을 지적 할 가치가 있습니다. `MY_CONSTANT = function () {return "some-other-value"; } 깨뜨립니다. +1, 괜찮고 빠른 솔루션.
Patrick M

13
-1. 이것은 var SOME_NAME = value (여전히 변경 가능)에 비해 이점이 없으며 더 많은 코드이며 설명이 필요합니다.
mikemaccana

@PatrickM 그것은 상수 수정할 수 없어야 하는 C와 같은 다른 언어에서 그러한 종류의 의사 상수를 수정할 수 있다는 것이 사실이지만, 포인터를 통해 여전히 할 수 있습니다. 최소한 상수라고 제안 하는 접근법을 사용하는 한 괜찮습니다.
rev

20

Mozillas MDN 웹 문서 에는에 대한 좋은 예와 설명이 들어 있습니다 const. 발췌 :

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

그러나 IE9 / 10이 여전히 지원하지 않는 것은 슬픈 일입니다 const. 그리고 그것이 터무니없는 이유 :

그래서 IE9는 const로 무엇을하고 있습니까? 지금까지 우리의 결정은 그것을지지하지 않는 것이 었습니다. 모든 브라우저에서 사용할 수 없었기 때문에 아직 컨센서스 기능이 아닙니다.

...

결국, 웹을위한 최상의 장기 솔루션은 웹을 떠나 표준화 프로세스가 진행될 때까지 기다리는 것 같습니다.

다른 브라우저가 올바르게 구현하지 않았기 때문에 구현하지 않습니까?! 더 나아 질까 두려운가요? 표준 정의 여부에 관계없이 상수는 상수입니다. 한 번 설정하면 절대 변경되지 않습니다.

그리고 모든 아이디어에 : 모든 기능을 덮어 쓸 수 있습니다 (XSS 등). 따라서 var또는에 차이가 없습니다 function(){return}. const유일한 상수입니다.

업데이트 : IE11 const 다음을 지원합니다 .

IE11은하자를 포함한 신흥 인 ECMAScript 6 표준의 잘 정의 일반적으로 사용되는 기능에 대한 지원이 포함 const, Map, Set, 및 WeakMap뿐만 아니라 __proto__향상된 상호 운용성.


25
"모든 브라우저에서 사용할 수있는 것은 아닙니다". IE에서 사용할 수 없으면 모든 브라우저에있는 것은 아닙니다.
km1

운전 표준화는 모든 사람을위한 것이 아닙니다.)-회사가 와서 다시 간다-나무의 확률을 인용 해 주셔서 감사합니다.
Quicker

VBA는 아직 모든 브라우저에서 컨세 서스 기능이 아니며 MS는 VBA에서 const를 지원합니다. 이는 개발 예산 채널링의 대가입니다.)
Quicker

17

함수를 사용하지 않아도되는 경우 :

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

이 방법을 사용하면 대신 일반 변수의 기능 제공하지만, 그것은 보장 * 아무도 그것의 설정하면 값을 변경할 수 없음.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

나는 개인적으로 녹아웃 옵저버 블 에서이 패턴에 익숙해지면 다소 유쾌하게 생각합니다.

* 누군가가 함수 constant를 호출하기 전에 함수 를 재정의하지 않은 경우


1
underscore.js는이 코드와 동일한 상수 함수를 구현합니다.
Upperstage

OP의 질문의 정신에 간단하고 간결하며 답변합니다. 더 많은 upVotes를 받았을 것입니다.
Mac

3
이것은 실제로 나를 위해 일한 적이 없습니다. 클로저가 불변이더라도 할당 한 변수를 덮어 쓸 수 있습니다. 예 : a = constant(10); a(10); // 10뒤에 a = constant(25); a(); //25오류나 경고가없고 상수가 손상되었다는 표시가 없습니다.
Patrick M

만약에 내가 재 할당 값을 a새로운 값으로 다음의 변화
Saurabh 샤르마

17

"새"Object API를 사용하면 다음과 같은 작업을 수행 할 수 있습니다.

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

한 번 봐 가지고 더 구체적인 내용 모질라 MDN에 있습니다. 객체에 첨부되어 있기 때문에 첫 번째 수준 변수는 아니지만 범위가 있으면 무엇이든 연결할 수 있습니다. this잘 작동합니다. 예를 들어 전역 범위 에서이 작업을 수행하면 의사 상수 값이 창에 선언됩니다 (실제로 나쁜 생각이므로 전역 변수를 부주의하게 선언해서는 안됩니다)

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

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

참고 : 할당하면 콘솔에서 할당 된 값이 다시 표시되지만 변수 값은 변경되지 않습니다.


사파리에서는 작동하지 않으며 다른 값으로 define 문을 다시 실행하면 mozilla에서 값이 다시 할당됩니다.
Akshay

2
'사파리에서 작동하지 않음', 사파리에서 지원 되지 않습니다 . 동일하지 않습니다. 그리고 시도하면 'Uncaught TypeError : 속성을 재정의 할 수 없습니다 : <property name here>'을 던져야합니다. 잘못하고 있거나 ff가 잘못 구현했습니다. 두 가지가 섞인 것 같습니다.
tenshou

14

가능한 경우 상수를 구조로 그룹화하십시오.

예를 들어, 현재 게임 프로젝트에서 아래를 사용했습니다.

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

할당:

var wildType = CONST_WILD_TYPES.REGULAR;

비교 :

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

더 최근에는 비교를 위해 사용하고 있습니다.

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

IE11에는 'const'선언이있는 새로운 ES6 표준이 있습니다.
위의 IE8, IE9 및 IE10과 같은 이전 브라우저에서 작동합니다.


12

설정할 수는 있지만 변경할 수없는 상수에 대한 메커니즘을 스크립트에 쉽게 장착 할 수 있습니다. 변경하려고하면 오류가 발생합니다.

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

IE를 잊고 const키워드를 사용하십시오 .


9
나를 위해 일한다! 근데 크롬 확장 프로그램을 작성하고 있는데, 제 브라우저를 제대로 운영하고 있다는 것을 알고 있습니다.
yoyo

1
확장 프로그램 및 애드온 작성에 대한 @yoyo의 가장 중요한 부분은 브라우저 간 지원이 아닙니다!
Ian

1
@Ian 2019 년에 오신 것을 환영합니다. 브라우저 간 불일치가 거의 사라졌습니다.)
Fusseldieb

9

그러나 브라우저 간 사전 정의 된 정확한 방법은 없지만 다른 답변에 표시된대로 변수 범위를 제어하여이를 달성 할 수 있습니다.

그러나 다른 변수와 구별하기 위해 네임 스페이스를 사용하는 것이 좋습니다. 이렇게하면 다른 변수와의 충돌 가능성이 최소화됩니다.

적절한 이름 공간

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

그래서 그것을 사용하는 동안 iw_constant.name또는iw_constant.age

Object.freeze 메소드를 사용하여 iw_constant 내에서 새 키를 추가하거나 키를 변경하는 것을 차단할 수도 있습니다. 그러나 레거시 브라우저에서는 지원되지 않습니다.

전의:

Object.freeze(iw_constant);

구형 브라우저의 경우 고정 방법에 polyfill 을 사용할 수 있습니다 .


함수 호출에 문제가 없으면 다음과 같이 상수를 정의하는 가장 좋은 브라우저 간 방법입니다. 자체 실행 함수 내에서 객체의 범위를 정하고 상수에 대한 get 함수를 반환합니다.

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

       };

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

// 값을 얻 iw_constant('name')거나iw_constant('age')


** 두 예제에서 이름 간격에 매우주의하여 객체 또는 함수를 다른 라이브러리를 통해 교체해서는 안됩니다 (객체 또는 함수 자체가 교체되면 전체 상수가 이동합니다)


7

잠시 동안, 나는 with()문에 전달 된 객체 리터럴에 "상수"(실제로 상수는 아님)를 지정했습니다 . 나는 그것이 너무 영리하다고 생각했다. 예를 들면 다음과 같습니다.

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

과거에는 CONST모든 상수를 넣을 네임 스페이스 도 만들었습니다 . 다시, 오버 헤드로. esh.

자, 난 그냥 할 var MY_CONST = 'whatever';KISS .


16
eval보다 더 악한 것이 있다면 그것은 분명 with합니다.
NikiC

4
평가는 매우 악하다! 내 집을 한 번 불태 웠어!
W3Geek

6

내 의견 (객체와 만 작동).

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

시험! 그러나 이해하십시오-이것은 객체이지만 단순한 변수는 아닙니다.

또한 시도하십시오 :

const a = 9;

5

나도 이것에 문제가 있었다. 그리고 꽤 오랫동안 답변을 찾고 모든 사람들의 모든 답변을 살펴본 후에 나는 이것에 대한 실용적인 해결책을 생각해 냈습니다.

내가 본 대부분의 답변은 상수를 유지하는 함수를 사용하는 것 같습니다. 많은 MANY 포럼 사용자가 게시 한 것처럼 클라이언트 측의 사용자가 기능을 쉽게 덮어 쓸 수 있습니다. Keith Evetts의 답변에 따르면 상수 객체는 외부에서 액세스 할 수 없으며 내부의 함수에서만 액세스 할 수 있습니다.

그래서 나는이 해결책을 생각해 냈습니다.

클라이언트 측에서 변수, 객체 등을 변경할 수 없도록 익명 함수 안에 모든 것을 넣습니다. 또한 다른 함수가 내부에서 '실제'함수를 호출하도록하여 '실제'함수를 숨 깁니다. 또한 클라이언트 측의 사용자가 기능을 변경했는지 확인하기 위해 함수를 사용하는 방법을 생각했습니다. 기능이 변경된 경우 내부에서 '보호'되어 있으며 변경할 수없는 변수를 사용하여 다시 변경하십시오.

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

또한 보안은 실제로 문제가되는 것으로 보이며 클라이언트 측에서 프로그래밍을 '숨길'수있는 방법이 없습니다. 저에게 좋은 생각은 프로그래머를 포함한 모든 사람이 읽고 이해하기가 어렵도록 코드를 압축하는 것입니다. 당신이 갈 수있는 사이트가 있습니다 : http://javascriptcompressor.com/ . (이것은 내 사이트가 아니며, 광고하지 않는다고 걱정하지 마십시오.)이 사이트는 Javascript 코드를 무료로 압축하고 난독 처리 할 수있는 사이트입니다.

  1. 위 스크립트의 모든 코드를 복사하여 javascriptcompressor.com 페이지의 상단 텍스트 영역에 붙여 넣습니다.
  2. Base62 인코딩 확인란을 선택하고 변수 축소 확인란을 선택하십시오.
  3. 압축 버튼을 누릅니다.
  4. 모든 파일을 .js 파일에 붙여 넣은 다음 페이지 헤드의 페이지에 추가하십시오.

이것은 포함 할 라이브러리로 멋지게 포장 할 수있는 좋은 솔루션입니다. 그러나이 코드에서 변수의 이름 지정을 싫어합니다. Keith의 코드에서 사용되는 "name"및 "value"와 같은 설명적인 이름을 삭제하는 이유는 무엇입니까? 사소한 문제이지만 여전히.
Cordle

5

분명히 이것은 표준화 된 크로스 브라우저 const 키워드의 필요성을 보여줍니다.

그러나 지금은 :

var myconst = value;

또는

Object['myconst'] = value;

둘 다 충분 해 보이고 다른 것은 바주카포로 비행하는 것과 같습니다.


좋은 오래된 var를 받아라 myconst = value; 디버깅을 위해 추가 디버깅 코드를 사용하십시오 ...-모든 브라우저가 const를 지원하지 않는 한 미친 것처럼 작동합니다.
Quicker

4

Greasemonkey 스크립트 const대신에 사용 var하지만 Firefox에서만 실행되기 때문입니다.
이름 규칙도 실제로 갈 수 있습니다 (두 가지 모두를 수행하십시오!).


4

JavaScript에서 내 연습은 가능한 한 상수를 피하고 대신 문자열을 사용하는 것입니다. 상수를 외부 세계에 노출하려고 할 때 상수 문제가 나타납니다.

예를 들어 다음과 같은 Date API를 구현할 수 있습니다.

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

그러나 간단하게 작성하는 것이 훨씬 짧고 자연 스럽습니다.

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

이 방법으로 "일"과 "시간"은 실제로 상수처럼 작동합니다. "시간"이 나타내는 초 수를 외부에서 변경할 수 없기 때문입니다. 하지만 쉽게 덮어 쓸 수 MyModule.Date.HOUR있습니다.

이러한 종류의 접근 방식은 디버깅에도 도움이됩니다. Firebug가 말하면 action === 18그것이 의미하는 바를 알아내는 것은 매우 어렵지만, 볼 때 action === "save"즉시 분명합니다.


불행히도 철자 실수를하는 것은 매우 쉬운 일 이지만 ( 예를 들어 "Hours"대신에) "hours"IDE가 Date.Hours정의하지 않은 것을 조기에 알려줄 수도 있습니다 .
le_m 2016 년

4

좋아, 이것은 추악하지만 Firefox와 Chromium에 상수, Safari와 Opera의 불변 상수 (WTF?) 및 IE의 변수를 제공합니다.

물론 eval ()은 악의적이지만 IE가 없으면 스크립트가 실행되지 못하게하는 오류가 발생합니다.

Safari와 Opera는 const 키워드를 지원하지만 const의 값을 변경할 수 있습니다 .

이 예제에서 서버 측 코드는 페이지에 JavaScript를 작성하여 {0}을 값으로 대체합니다.

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

이것이 좋은 점은 무엇입니까? 크로스 브라우저가 아니기 때문에 별로는 아닙니다. 기껏해야 적어도 마음의 평화가 일부 브라우저는 북마크 나 타사 스크립트가 값을 수정하도록 허용하지 않을 수도 있습니다.

Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9에서 테스트되었습니다.


1
그 코드를 좋아하십시오! 추악하지만 const 지원에 대한 좋은 테스트입니다. =)
Stein G. Strindhaug

1
다소 웃긴, 즉-const를 선언하기 위해 몇 줄을 입력 할 수 있습니까?
Quicker

4

언급 할 가치가있는 경우 다음을 사용하여 상수를 각도로 정의 할 수 있습니다$provide.constant()

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

... 그리고 VBA에서 const를 사용할 수 있습니다 ... xbrowser? ... ups ...;)
Quicker

OP는 자바 스크립트에 대해 묻고 답변은 특정 의견이 많은 JS 프레임 워크를 처리합니다. 실질적으로 주제가 맞지 않습니다.
반송

2
@rounce : 오프 주제 답변, 아직 답변하지 않습니다 있습니다 플래그 그들은 하지 않음은 응답 하지만 downvote삭제 투표 대신은. “응답 아님”플래그를 올바르게 사용하는 방법을
Kevin Guan

@KevinGuan 참고, 앞으로 할 것입니다.
반송

4

대신 Burke의 답변 을 개선했습니다 .CONFIG.MY_CONSTCONFIG.get('MY_CONST')

IE9 + 또는 실제 웹 브라우저가 필요합니다.

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

* 초기 값을 변경할 수없는 경우에만 속성이 읽기 전용입니다.


4

JavaScript ES6 는 모든 주요 브라우저 에서 지원되는 const키워드 를 다시 도입했습니다 .

via를 통해 선언 된 변수는 const다시 선언하거나 재 할당 할 수 없습니다.

그 외에도에서, const유사 동작합니다 let.

기본 데이터 유형 (부울, 널, 정의되지 않음, 숫자, 문자열, 기호)에 대해 예상대로 작동합니다.

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

주의 : 물체와 관련된 함정에 유의 하십시오.

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

불변이고 절대적으로 일정한 객체가 정말로 필요한 경우 : const ALL_CAPS의도를 명확하게하기 위해 사용하십시오. const어쨌든 모든 선언 을 따르는 것이 좋은 규칙 이므로 그에 의존하십시오.


에서 IE11 에만 :-(
Mo.

3

다른 대안은 다음과 같습니다.

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

그런 다음 간단히 : var foo = constantMap.MY_CONSTANT

당신이 인 경우에 constantMap.MY_CONSTANT = "bar"우리는 게터와 할당 연산자를 사용하려는으로 영향을 미치지 않을 것이다 그것은, 따라서 constantMap.MY_CONSTANT === "myconstant"진정한 남아있을 것입니다.


3

Javascript에는 이미 상수가 있습니다. 다음과 같이 상수를 정의하십시오.

const name1 = value;

재 할당을 통해 변경할 수 없습니다.


답변의 링크 당, 이것은 실험적인 기능이므로주의해서 사용해야합니다.
Johnie Karr

물론 동의합니다. 그러나 최신 버전의 브라우저에서는 작동합니다.
Erik Lucio 2016 년

3

키워드 'const'는 이전에 제안되었으며 현재 공식적으로 ES6에 포함되었습니다. const 키워드를 사용하면 불변 문자열로 작동하는 값 / 문자열을 전달할 수 있습니다.


2

JavaScript에 상수를 도입하는 것은 최선의 방법입니다.

JavaScript에서 지속적으로 전역 적으로 액세스 가능한 값을 만드는 좋은 방법은 다음과 같은 "읽기 전용"속성으로 객체 리터럴을 선언하는 것입니다.

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

모든 상수는 하나의 "my"액세서리 객체로 그룹화되어 저장된 값 또는 해당 사안에 대해 결정한 다른 것을 찾을 수 있습니다. 이제 작동하는지 테스트 해 봅시다.

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

보다시피, "my.constant1"속성은 원래 값을 유지했습니다. 당신은 멋진 '녹색'임시 상수를 만들었습니다 ...

물론 이것은 주어진 예제에서와 같이 직접 액세스하여 속성 상수 값을 실수로 수정, 변경, 무효화 또는 비우는 것만 방지합니다.

그렇지 않으면 여전히 상수가 인형을위한 것이라고 생각합니다. 그리고 난 여전히기만적인 안보의 작은 구석에 대한 당신의 큰 자유를 교환하는 것이 가능한 최악의 거래라고 생각합니다.


2

Rhino.jsconst위에서 언급 한 것 외에도 구현합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.