Чи є константи в JavaScript?


1132

Чи існує спосіб використання констант у JavaScript ?

Якщо ні, то яка загальна практика вказувати змінні, які використовуються як константи?


35
Chromeдозволяє використовувати ключове слово constдля використання констант. напр const ASDF = "asdf". Однак, оскільки constвін не сумісний з декількома браузерами, я зазвичай дотримуюся varдекларації.
Jacksonkr

20
try{const thing=1091;}catch(e){var thing=1091;}працює.
Дерек 朕 會 功夫

13
Дерек: чи не обмежував би ваш тест / ловити обсяг того, що ви заявляєте, до блоку спробу / лову? Якщо ви не здійснюєте належну оцінку, то в чому сенс вказувати constабо varвзагалі?
Coderer

8
@Coderer у поточних реалізаціях це буде працювати, оскільки constмає ту ж область var, що і, і це на рівні функцій, а не на рівні блоків. Якщо ви будете слідувати майбутньому стандарту ECMAScript, він constмає таку ж область let, що і означає, що він не працюватиме.
Джаспер

3
@Coderer Неправильна мова. Змінні в JavaScript є сферою функціонування. Це не C.
doug65536

Відповіді:


1018

Починаючи з ES2015 , JavaScript має поняття const:

const MY_CONSTANT = "some-value";

Це буде працювати майже у всіх браузерах, крім IE 8, 9 та 10 . Деяким може бути потрібен суворий режим .

Ви можете використовувати varдля таких конвенцій, як ALL_CAPS, щоб показати, що певні значення не слід змінювати, якщо вам потрібно підтримувати старіші веб-переглядачі або працюєте зі застарілим кодом:

var MY_CONSTANT = "some-value";

60
Як щодо const x = 24;
Захарі Скотт

93
Зауважте, що якщо вам не потрібна сумісність між браузерами (або ви програмуєте на сервері на Rhino або Node.js), ви можете використовувати constключове слово. На даний момент його підтримують усі сучасні браузери, крім IE.
Хаскі

17
Ці дні (через 3,5 роки) можна використовувати Object.definePropertyдля створення властивостей лише для читання, які також не можна видалити. Це працює в поточній версії всіх основних браузерів (але неправильно в IE8 ). Дивіться відповідь @NotAName
Фрогз

12
@Amyth Це не дуже корисно. Це посібник зі стилів, запропонований єдиним постачальником. Згідно з вищезазначеним питанням Хаскі, сумісність IE абсолютно не має значення при написанні JS на стороні сервера.
aendrew

32
Оскільки Google відповідь все ще високо оцінив у 2015 році, слід сказати, що вона зараз застаріла. Зараз constключове слово офіційно є частиною мови і підтримується кожним браузером. За даними statcounter.com, лише кілька відсотків користувачів Інтернету досі використовують старі версії браузера, які не підтримують const.
тристан

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

Використовуючи такий підхід, значення неможливо змінити. Але вам потрібно використовувати метод get () на CONFIG :(.

Якщо вам не потрібно суворо захищати значення змінних, просто виконайте, як було запропоновано, і використовуйте конвенцію ВСІХ CAPS.


13
Зауважте, що ви можете просто повернути функцію для значення CONFIG. Це дозволить вам весь час зателефонувати на CONFIG.get ().
Mathew Byrne

4
Гарне рішення. Але такі речі слід обернути як бібліотеку, щоб не винаходити їх у будь-якому новому проекті.
Андрій

82
CONFIG.get = someNewFunctionThatBreaksTheCode... Загалом, ви абсолютно не можете застосувати константи в JS (без ключового слова const). Щодо єдиного, що ви можете зробити, це обмежити видимість.
Томас Едінг

28
Я вважаю, що privateце майбутнє зарезервоване слово в JavaScript, я б не використовував це, якби я був ти.
Зак

Це також схема реєстру.

122

constКлючове слово в проекті ECMAScript 6 , але при цьому він користується поки тільки невеликою кількістю підтримки браузера: http://kangax.github.io/compat-table/es6/ . Синтаксис:

const CONSTANT_NAME = 0;

13
Якщо ви спробуєте призначити значення a const, воно не видасть помилок. Присвоєння просто не вдається, і константа все ще має своє початкове значення. Це головний недолік IMHO в дизайні, але, поки існує чітка, послідовна конвенція щодо іменування (наприклад, популярна ALL_CAPS), я не думаю, що це спричинить занадто багато горя.
MatrixFrog

6
Слідкуйте за підтримкою браузера тут: kangax.github.io/es5-compat-table/es6/#const
Марк Макдональд

6
Призначення @MatrixFrog призведе до помилки з 'use strict'.
Сам

Чи слід визначати константи в ALL CAPS?
Льюїс

1
@Tresdin Це загальна умова іменування для визначення констант у всіх великих літери. Ніщо в мовній специфікації це не змушує, але це не погана ідея. Це робить більш зрозумілим, який ваш задум, і це покращує читабельність коду.
Білл Ящірка

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
Альнітак

Примітка: це поводиться аналогічно constдекларації ES6 , наприклад, властивості не можна повторно оголошувати або перепризначати, але якщо вони мають тип даних object, вони можуть бути вимкнено.
le_m

Саме те, що я шукав. Ви також можете використовувати const constantsзамість того, var constantsщоб запобігти перепризначенню змінної.
Джаретт Міллард

Дивіться, наприклад, глибоке заморожування для рекурсивного заморожування.
сам

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 для роздумів трохи поза рамками.
Том

14
VBScript? Що це? ;)
tybro0103

2
Зазвичай я голосую за загальнозв’язане запитання між перехресними браузерами з конкретною відповіддю IE. Тому що я ненавиджу людей, які думають, що реалізація JavaScript IE - це "Єдине", а інших просто ігнорувати. Хто використовує інші борсери, ніж IE, btw?
Мураха

@Cooluhuru цей скрипт, як видається, обробляє як браузери IE (за допомогою VBScript), так і не-IE-браузери (за допомогою JavaScript const). Чи можете ви пояснити, що з цим не так?
Ендрю Грімм

Я все ще важко приймаю, що константи можна змінювати.
Норберт Норбертсон

59

ECMAScript 5 вводить Object.defineProperty:

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

Він підтримується у кожному сучасному браузері (як і IE ≥ 9).

Дивіться також: Object.defineProperty в ES5?


1
Варто зазначити, що це не схоже на традиційну константу. Це дозволить лише визначити постійну властивість (непостійного об'єкта). Також це не створює помилки і навіть повертає значення, яке ви намагаєтесь встановити. Він просто не пише значення.
Cory Gross

3
Нещодавно я прочитав, що спроба призначити властивість за допомогою насправді writable: false призведе до помилки, якщо код, який виконує призначення, інтерпретується в суворому режимі ECMAScript 5. Просто ще одна причина для запису 'use strict'у свій код.
Cory Gross

6
Ви можете фактично опустити, writable: falseоскільки це за замовчуванням .
сам

24

Ні, не взагалі. Firefox реалізує, constале я знаю, що IE не робить.


@John вказує на загальну практику іменування для consts, яка роками використовується іншими мовами, я не бачу причин, чому ви не могли б цим скористатися. Звичайно, це не означає, що хтось не запише значення змінної. :)


11
Як всім відомо, якщо IE не реалізує його, він може також не існувати.
Джош Хінман

3
На жаль, і практично кажучи - це правда. IE володіє величезною часткою ринку. Якби я володів бізнесом і використовував внутрішньо веб-додатки, я б стандартизував FF. Я не знаю, чому так багато людей піклується про IE, це дме.
Джейсон Бантінг

@Rich: Хто сказав, що моя думка є фактом? Ви зробили цілком припущення. Крім того, що стосується мене, то факт, що IE смокче, є фактом. Ви можете мати свої факти, я не казав, що ви повинні вірити моїм. : P Візьміть Ксанакс чи що-небудь ...
Джейсон Бантінг

@ Rich B, так, це був просто німий коментар, і, повірте, я б знав, я роблю безліч німих коментарів. @Jason B. - Цікаво, я зіткнувся з цією самою проблемою минулої ночі .. Конст працював у FF, але не в IE. Дякуємо за уточнення

Хто дбає про IE? Я не! FF або Chrome, Opera тощо ... можна встановити майже на будь-якій платформі ОС. Також роздрібні торговці комп’ютерами зазвичай знають, що стара версія IE є відстійною, тому вони часто (або навіть кожен раз) встановлюють альтернативні веб-переглядачі перед продажем комп'ютера. Тому я вирішив, що розроблений додаток взагалі не піклується про несумісні браузери: якщо розробники браузерів піклуються про дотримання стандартів, їхній продукт може використовувати мій додаток, якщо ні, користувачі будуть використовувати інший браузер ... я можу з цим жити; -) Але чи може Microsoft жити, втрачаючи частину ринку? Ні, вони не можуть так "Вони" змінить політику свого розробника!
willy winka

20

У JavaScript я вважаю за краще використовувати функції для повернення постійних значень.

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


alert(MY_CONSTANT());

6
Варто зазначити, що це потрапляє в ту саму проблему, згадану у відповіді @Burkes (коментар @trinithis). `MY_CONSTANT = function () {return" якесь інше значення "; } ламає його. +1, хоча, гідне та швидке рішення.
Патрік М

13
-1. Це не має переваги над var SOME_NAME = значення (воно все ще змінюється), більше коду та вимагає пояснення.
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, він ніколи не буде у всіх браузерах.
км1

Стандартизація водіння не для всіх;) - компанії приїжджають і знову їздять - дякую за цитування шансів у лісі
Швидше

ще одне з цього приводу: VBA ще не є функцією consesus у всіх браузерах, а MS підтримує const у VBA - це майстерність спрямування бюджетів розвитку;)
Швидше

17

Якщо ви не проти використовувати функції:

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

Цей підхід дає вам функції замість регулярних змінних, але він гарантує *, що ніхто не може змінювати значення після встановлення.

a = constant(10);

a(); // 10

b = constant(20);

b(); // 20

Мені особисто це здається приємним, особливо після того, як я звик до цього шаблону від спостереження за нокаутом.

* Якщо хтось не визначив функцію constantперед тим, як ви її зателефонували


1
underscore.js реалізує постійну функцію, ідентичну цьому коду.
Верхня сцена

Простий, стислий та відповідає на запитання ОП. Це повинно було отримати більше голосів.
Mac

3
Це ніколи насправді не працювало для мене. Незважаючи на те, що закриття робить його непорушним, вар, якому ви його призначили, все одно може бути перезаписаний. Напр .: a = constant(10); a(10); // 10слідом за цим a = constant(25); a(); //25, жодних помилок чи попереджень, жодних ознак того, що ваша константа була порушена.
Патрік М

Якщо я переставлю значення, aто воно зміниться на нове значення
Saurabh Sharma

17

з "новим" api-об'єктом ви можете зробити щось подібне:

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

Погляньте на це на MDN Mozilla, щоб отримати детальнішу інформацію. Це не змінна система першого рівня, оскільки вона прикріплена до об'єкта, але якщо у вас є сфера, будь-що, ви можете приєднати її до цього. thisповинні також працювати. Так, наприклад, зробивши це в глобальному масштабі, буде оголошувати псевдоконстантное значення у вікні (це дійсно погана ідея, ви не повинні оголошувати глобальну варс необережно)

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

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

Примітка: призначення поверне вам присвоєне значення в консолі, але значення змінної не зміниться


Не працює в safari і в mozilla, якщо ви знову виконаєте команду define - з іншим значенням - вона переназначить це значення.
Акшай

2
Не працює в сафарі, не підтримується в сафарі. Не те ж саме. І він повинен кинути "Uncaught TypeError: Неможливо перевзначити властивість: <ім'я властивості тут>", якщо ви спробуєте це. або ви робите це неправильно, або ваш 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 - це новий стандарт ES6, який має "const" декларацію.
Вище працює у попередніх браузерах, таких як 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 найкраща частина про написання розширень та аддонів - немає підтримки між браузером!
Ян

1
@Ian Ласкаво просимо до 2019 року, невідповідність крос-браузера майже зникла :)
Fusseldieb

9

І все-таки немає точного крос-браузерного заздалегідь визначеного способу зробити це, ви можете досягти цього, контролюючи область змінних, як показано в інших відповідях.

Але я запропоную використовувати простір імен, щоб відрізнити їх від інших змінних. це зменшить шанс зіткнення до мінімуму з інших змінних.

Правильний простір імен, як

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

тому під час його використання буде iw_constant.nameабоiw_constant.age

Ви також можете заблокувати додавання будь-якого нового ключа або змінити будь-який ключ всередині iw_constant, використовуючи метод Object.freeze. Однак його не підтримується у застарілому браузері.

колишній:

Object.freeze(iw_constant);

Для старшого браузера ви можете використовувати метод polyfill for freeze.


Якщо ви все в порядку з функцією виклику, наступним є найкращий спосіб перехресного браузера для визначення константи. Оцінка об'єкта в межах функції самовиконання та повернення функції отримання констант:

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простір імен, куди б розмістив усі свої константи. Знову з накладними. Шиш.

Тепер, я просто var MY_CONST = 'whatever';в КИСС .


16
Якщо є щось більше зло, ніж евал, це однозначно with.
NikiC

4
eval - це дуже зло! Це один раз спалило мій будинок!
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

У мене теж були проблеми з цим. І після досить довгого пошуку відповіді та перегляду всіх відповідей усіх, я думаю, що я придумав життєздатне рішення цього питання.

Здається, більшість відповідей, які я натрапила, - це використання функцій для утримання констант. Оскільки багато користувачів форумів МНОГО публікують, функції можуть бути легко написані користувачами на стороні клієнта. Мене заінтригувала відповідь Кіта Еветтса про те, що до об'єкта констант не можна дістатись іззовні, а лише з функцій зсередини.

Тому я придумав таке рішення:

Помістіть все всередині анонімної функції, щоб таким чином змінні, об'єкти тощо не могли бути змінені стороною клієнта. Також приховайте «реальні» функції, якщо інші функції викликають «реальні» функції зсередини. Я також думав про використання функцій, щоб перевірити, чи змінена функція користувачем на стороні клієнта. Якщо функції були змінені, поверніть їх назад, використовуючи змінні, які 'захищені' зсередини і не можуть бути змінені.

/*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-файл та додайте його на свою сторінку в заголовку сторінки.

Це хороше рішення, яке можна було б добре включити як бібліотеку для включення. Але мені не подобається називати ваші змінні в цьому коді. Навіщо відкидати описові назви, такі як "ім'я" та "значення", як вони використовуються в коді Кіта? Незначне питання, але все ж.
Cordle

5

Зрозуміло, що це свідчить про необхідність стандартизованого ключового слова const для перехресного браузера.

Але поки що:

var myconst = value;

або

Object['myconst'] = value;

І те, і інше здається достатнім, і все інше, як зйомка мухи базукою.


взяти старий добрий var myconst = значення; а для налагодження використовуйте додатковий код налагодження ... - працює як божевільний, якщо не всі браузери підтримують const
Швидше

4

Я використовую constзамість varсвоїх сценаріїв Greasemonkey, але це тому, що вони працюватимуть лише на Firefox ...
Конвенція про імена може бути справді шляхом (я обоє!).


4

У JavaScript моя практика полягала в тому, щоб максимально уникати константи і використовувати натомість рядки. Проблеми з константами з’являються, коли ви хочете виставити константи зовнішньому світу:

Наприклад, можна реалізувати такий API 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

4

Гаразд, це некрасиво, але це дає мені постійну в Firefox та Chromium, непостійну константу (WTF?) У Safari та Opera та змінну в 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. =)
Штейн Г. Стріндгауг

1
дещо смішно, ей - скільки рядків можна набрати, щоб оголосити const?
Швидше

4

Якщо це варто згадати, можна визначити константи в кутових за допомогою$provide.constant()

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

... і ви можете використовувати const у VBA ... xbrowser? ... ups ...;)
Швидше

ОП запитує про javascript, відповідь стосується конкретних рамок JS, що дуже добре знають. Практично поза темою.
круглий

2
@rounce: Поза тематичні відповіді все ще є відповідями, не позначайте їх як Not Answer, а знизу і голосуйте за видалення . Див. Як я правильно використовую прапор "Не відповідь"?
Кевін Гуан

@KevinGuan Помітив, зробить це в майбутньому.
круглий

4

Удосконалена версія відповіді Берка, яка дозволяє робити це CONFIG.MY_CONSTзамість CONFIG.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ключове слово, яке підтримується у всіх основних браузерах .

Змінні, оголошені через, 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 тільки :-(
Мо

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"це зробили, це не матиме жодного ефекту, оскільки ми намагаємось використовувати оператор присвоєння разом із getter, отже, constantMap.MY_CONSTANT === "myconstant"це залишиться правдою.


3

у Javascript вже є константи . Ви визначаєте константу так:

const name1 = value;

Це не може змінитися через перепризначення.


За посиланням у відповіді це експериментальна особливість, і його слід використовувати обережно.
Джонні Карр

Звичайно, я з вами згоден. Але в останніх версіях браузерів це працює.
Ерік Луціо

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.constant1; >> "constant 1" 
           my.constant1 = "new constant 1";
           my.constant1; >> "constant 1" 

Як ми бачимо, властивість "my.constant1" зберегла своє первісне значення. Ви зробили собі приємні «зелені» тимчасові константи ...

Але, звичайно, це лише захистить вас від випадкового зміни, зміни, зведення нанівець чи спорожнення постійної вартості вашого власності за допомогою прямого доступу, як у наведеному прикладі.

Інакше я все ще думаю, що константи призначені для муляжів. І я все ще думаю, що обмін вашої великої свободи на невеликий куточок оманливої ​​безпеки - це найгірша можлива торгівля.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.