Вартість в JavaScript: коли ним користуватися і чи потрібно це?


349

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

const x = 'const';
const x = 'not-const';

// Will give an error: 'constant 'x' has already been defined'

Я розумію, що він ще не стандартизований у всіх браузерах - але мене цікавить лише контекст Node.js V8 , і я помітив, що певні розробники / проекти, здається, віддають перевагу цьому, коли varключове слово може використовуватися для той же ефект.

Тому мої запитання:

  • Коли доцільно використовувати constзамість var?
  • Чи слід його використовувати щоразу, коли оголошується змінна, яка не буде переназначена?
  • Чи насправді це має значення, якщо varвін використовується замість цього constчи навпаки?

1
Здається, це ще не стандартизовано (можливо, у EC6?). Додаткову інформацію про це ви знайдете тут: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Sebastien C.

1
Const має погані показники, хоча jsperf.com/const-vs-var-mod-3
Deepu

Відповіді:


462

У ваших запитаннях є два аспекти: які технічні аспекти використання constзамість цьогоvar та які аспекти цього стосуються людини.

Технічна різниця значна. У компільованих мовах константа буде замінена під час компіляції, і її використання дозволить проводити інші оптимізації, такі як видалення мертвого коду, для подальшого підвищення ефективності виконання коду. Нещодавні (вживаний термін) двигуни JavaScript фактично компілюють JS-код, щоб досягти кращої продуктивності, тому використання ключового слова const сповістить їх про те, що описані вище оптимізації можливі і їх потрібно робити. Це призводить до кращих показників.

Людський аспект стосується семантики ключового слова. Змінна - це структура даних, яка містить інформацію, яка, як очікується, зміниться. Константа - це структура даних, яка містить інформацію, яка ніколи не зміниться. Якщо є місце для помилки, varзавжди слід використовувати. Однак не всю інформацію, яка ніколи не змінюється протягом життя програми, потрібно задекларувати const. Якщо за інших обставин інформація повинна змінюватися, використовуйте varдля позначення цього, навіть якщо фактична зміна не відображається у вашому коді.


4
Здрастуйте, я припустив, що Mozilla / Google без жодної причини не додадуть const підтримку двигунам JS. Я обов’язково використовую const, де це можливо.
axdg

6
constоб'єкти здаються незмінними, тому я не впевнений, наскільки суворим є компілятор JS. Можливо, режим «використовувати суворий» теж має значення.
Rudie

9
@Rudie Функція, яку ви шукаєте, називається заморожуванням об'єкта. constпросто запобігає переназначенню "змінної" на інше значення. const a = {}; a = {};видасть помилку в суворому режимі.
Тібос

Я взагалі використовую const замість дозволу для більшості змінних, так само, як у Java я додаю остаточну до більшості змінних оголошень.
кодування

2
If there is room for error, var should always be used. Сьогодні це більше не застосовується, коли такі інструменти, як ESLint, вказують на constпорушення відразу.
vitaly-t

72

Оновлення 2017 року

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


Оригінальний відповідь від 2014 року

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

Поточна реалізація const є специфічним для Mozilla розширенням і не є частиною ECMAScript 5. Він підтримується в Firefox & Chrome (V8). Станом на Safari 5.1.7 та Opera 12.00, якщо ви визначаєте змінну з const у цих браузерах, ви можете змінити її значення пізніше. Він не підтримується в Internet Explorer 6-10, але включений в Internet Explorer 11. Ключове слово const в даний час оголошує константу в області функцій (як змінні, оголошені з var).

Потім він продовжує говорити:

constвизначатиметься ECMAScript 6, але з різною семантикою. Подібно до змінних, оголошених в операторі let, константи, оголошені const, будуть блоковані.

Якщо ви все-таки використовуєте, constвам доведеться додати рішення для підтримки трохи старших браузерів.


6
Чудова відповідь - хоча я вже читав статтю про MDN. Як я вже говорив, мене більше цікавило, чи дійсно V8 збирається по-різному ставитися до const. Я думаю, що @Tibos це очистив.
axdg

Джеймс дякує, що вказав на підтримку. Імхо, усі відповіді на JavaScript повинні включати розбитку підтримки браузера. чудово пояснено
hubson bropa

4
Примітка ES6 отримав функцію заморожування функцій у серпні 2014 року. У липні 2015 року стандарт був офіційно випущений. Якщо ви читаєте це зараз, це означає, що вам слід дотримуватися прийнятої відповіді, як зазначено, якщо вашим кодом керує сучасний механізм.
Філіп Дупанович

Питання про ОП конкретно node.js
Ніку Сурду

@NicolaeSurdu впевнено. Це також з січня 2014 року, тому, мабуть, здебільшого зайве зараз у 2017 році.
Джеймс Доннеллі

41

Для чого використовувати const, відповідь @ Tibos чудова.

Але ти сказав:

З того, що я можу сказати, він використовується для створення незмінних змінних

Це неправильно . Вимкнення змінної відрізняється від перепризначення:

var hello = 'world' // assigning
hello = 'bonjour!' // reassigning

З const, ви не можете цього зробити:

const hello = 'world'
hello = 'bonjour!' // error

Але ви можете вимкнути змінну:

const marks = [92, 83]
marks.push(95)
console.log(marks) // [92, 83, 95] -> the variable has been mutated.

Отже, будь-який процес, який змінює значення змінної без використання= знака, мутує зміну.

Примітка: +=наприклад, це ... перепризначення!

var a = 5
a += 2 // is the same as a = a + 2

Отже, суть полягає в тому, що: constне заважає вам мутувати змінні, заважає повторно призначити їх.


4
ваше твердження "будь-який процес, який змінює значення змінної без використання =знака, глушить" технічно неправильний. Наприклад, const marks=[92,83]; marks[2]=95; console.log(marks)буде вихід [92, 83, 95]. marksбуло вимкнено через знак рівності.
chharvey

5
"Але ви сказали: << З того, що я можу сказати, він використовується для створення незмінних змінних >> Це неправильно . Мутація змінної відрізняється від перепризначення" Ні, це не так. Переназначення змінює змінну. Ви говорите про вимкнення об'єкта, на яке посилається змінна. Це зовсім інша річ.
TJ Crowder

Потрапив сюди, тому що я намагаюся зрозуміти constв контексті масивів (подібний до прикладу @chharvey, який використовується). У разі повторно призначається кожен раз. То навіщо використовувати, а ні ? const countArray = countup(n - 1); countArray.push(n);constconstvar
YCode

1
@YCode № коли ви використовуєте const countArray, він ніколи не буде перепризначений. Ви все ще можете натиснути на масив, який змінює його члени та довжину, але ми не називаємо це перепризначенням. ви використовуєте constзамість цього letабо varколи ви хочете не допустити перепризначення. До речі , якщо ви дійсно хочете , щоб перепризначити, letмайже завжди краще , ніж var.
chharvey

@chharvey Дякую! Ваша відповідь призвела до того, що я "перейшов через значення проти пройти посилання", нову концепцію та дивну - де зміна значення - переназначення. Будь потребує в подальшому поясненні слід перевірити відповіді тут: stackoverflow.com/q/46131828/5965865
YCode

38

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

Наприклад, порівняйте:

// Will output 'SECRET'

const x = 'SECRET'
if (x = 'ANOTHER_SECRET') {  // Warning! assigning a value variable in an if condition
    console.log (x)
}

з:

// Will output 'ANOTHER_SECRET'

var y = 'SECRET'
if (y = 'ANOTHER_SECRET') { 
    console.log (y)
}

або

// Will throw TypeError: const 'x' has already been declared

const x = "SECRET"

/*  complex code */

var x = 0

з

// Will reassign y and cause trouble

var y = "SECRET"

/*  complex code */

var y = 0

Вам слід сказати, що ця "незмінна" поведінка застосовна лише для рядків, базових типів. Використовуючи об'єкти, масиви тощо, можна змінити значення, але неможливо повторно призначити новий "об'єкт", наприклад const a = ["a", "b"]; a = []; викине помилку, інакше можливо
Fer До

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

Використання const дуже схоже на модифікатори доступу, справжня незмінність - не мета.
StingyJack

32

constне є незмінним.

Від MDN :

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


24
Це трохи вводить в оману. Для чисел, рядків, булевих тощо (примітивів) constнезмінне. Для об'єктів і масивів його не можна перепризначити, але вміст можна змінити (наприклад, array.push).
Флоріан Вендельборн

2
Примітиви JS завжди незмінні. Використовуєте ви constчи ні, це не впливає.
12Me21

1
@Dodekeract тому не є незмінним за визначенням. Якщо значення можуть змінюватися, це не змінюється, хоча воно функціонує як незмінне для перерахованих вами примітивів
Ентоні

13

var : оголосити змінну, ініціалізація значення необов'язковою.

let : оголосити локальну змінну з областю блоку.

const : оголосити константу лише для читання.

Наприклад:

var a;
a = 1;
a = 2;//re-initialize possible
var a = 3;//re-declare
console.log(a);//3

let b;
b = 5;
b = 6;//re-initiliaze possible
// let b = 7; //re-declare not possible
console.log(b);

// const c;
// c = 9;   //initialization and declaration at same place
const c = 9;
// const c = 9;// re-declare and initialization is not possible
console.log(c);//9
// NOTE: Constants can be declared with uppercase or lowercase, but a common
// convention is to use all-uppercase letters.

10

У вас є чудові відповіді, але давайте просто.

const слід використовувати, коли у вас є визначена константа (читайте як: вона не зміниться під час виконання вашої програми).

Наприклад:

const pi = 3.1415926535

Якщо ви думаєте, що це щось, що може бути змінено при подальшому виконанні, тоді скористайтеся a var.

Практична різниця, виходячи з прикладу, полягає в тому, що з constвами завжди будете вважати, що пі буде 3,14 [...], це факт.

Якщо визначити його як a var, це може бути 3.14 [...] чи ні.

Для отримання більш технічної відповіді @Tibos є академічно правильним.


7

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

Помилка у вашому тестуванні - інша річ, але ви прагнете зробити ще одну змінну, що називається x, це був би більш точний тест.

const x = 'const';
x = 'not-const';

9
Я розумію, що ти маєш на увазі, але - смішно, що "постійне" для тебе означає "те, що я, можливо, хочу змінити". : P
Venryx

4

Особисті переваги дійсно. Ви можете використовувати const, коли, як ви кажете, він не буде перепризначений і є постійним. Наприклад, якщо ви хотіли призначити день народження. Ваш день народження ніколи не змінюється, щоб ви могли використовувати його як постійну. Але ваш вік змінюється так, що може бути змінною.


17
Це був би дуже давній сценарій!
знесення нанівець

3
@ nullability Залежить від того, скільки років ви відстежуєте. Більше декількох десятків, і сценарій не потрібно буде працювати довго :).
Міллі Сміт

4

Підсумок:

const створює незмінне значення прив'язки, ідентифікатор змінної const не може бути повторно призначений.

const a = "value1";

ви не можете повторно призначити його за допомогою

a = "value2";

Однак якщо ідентифікатор const містить об'єкт або масив, його значення може бути змінено, якщо ми не присвоїмо його повторно.

const x = { a: 1 }

x.a = 2; //is possible and allowed

const numbers = [1, 2];
numbers.push(3); //is possible and allowed

Зауважте, що const - це блок-область, подібно до того, що нехай не є таким же, як var (що має функцію)

Коротше кажучи, коли щось не зміниться через повторне призначення, використовуйте const else use let or var залежно від сфери, яку ви хочете мати.

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


2

Він забезпечує: 1) постійну посилання, наприклад, const x = [] - масив можна змінювати, але x не може вказувати на інший масив; та 2) блок-масштаб. const і нехай разом замінять var у ecma6 / 2015 Дивіться дискусію на https://strongloop.com/strongblog/es6-variable-declarations/


2
Main point is that how to decide which one identifier should be used during development.
In java-script here are three identifiers.

1. var (Can re-declared & re-initialize)
2. const (Can't re-declared & re-initialize, can update array values by using push)
3. let (Can re-initialize but can't re-declare)

'var': У момент кодування, коли ми говоримо про стандартний код, тоді ми зазвичай використовуємо ім'я ідентифікатора, який легко зрозуміти іншим користувачеві / розробнику. Наприклад, якщо ми працюємо, ми думаємо, що багато функцій, де ми використовуємо деякий ввід, обробляємо це і повертаємо певний результат, наприклад:

**Example of variable use**

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2;
 return result;
}

У наведених вище прикладах обидві функції дають різні результати 2, але використовують однакову назву змінних. Тут ми бачимо, що "процес" і "результат" обидва використовуються як змінні, і вони повинні бути.

 **Example of constant with variable**

 const tax = 10; 
 const pi = 3.1415926535; 

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

Перш ніж використовувати "Let" у Java-скрипті, ми маємо додати "use strict" у верхній частині файлу js

 **Example of let with constant & variable**

 const tax = 10; 
 const pi = 3.1415926535; 
 let trackExecution = '';

function firstFunction(input1,input2)
{
 trackExecution += 'On firstFunction'; 
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 trackExecution += 'On otherFunction'; # can add current time 
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

 firstFunction();
 otherFunction();
 console.log(trackExecution);

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


1

По-перше, три корисні речі const(крім поліпшень сфери, якими вона ділиться let):

  • Пізніше він документує тим, хто читає код, що значення не повинно змінюватися.
  • Це заважає вам (або комусь, хто йде за вами) змінювати значення, якщо вони не повернуться і не змінять декларацію навмисно.
  • Це може врятувати механізм JavaScript деякий аналіз з точки зору оптимізації. Наприклад, ви заявили, що значення не може змінюватися, тому двигун не повинен працювати, щоб з'ясувати, чи змінюється значення, щоб він міг вирішити, чи оптимізувати його на основі значення, яке не змінюється.

Ваші запитання:

Коли доцільно використовувати constзамість var?

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

Чи слід його використовувати щоразу, коли оголошується змінна, яка не буде переназначена?

Це залежить від вас / вашої команди.

Чи насправді це має значення, якщо var is used in place ofconst` чи навпаки?

Так:

  • varі constмають різні правила застосування. (Ви , можливо, хотіли порівняти з letчим var.) В зокрема: constі letблокова області дії, а при використанні в глобальному масштабі, не створюють властивості на глобальному об'єкті (незважаючи на те, що вони дійсно створюють глобал).varмає або глобальну область (якщо використовується в глобальному масштабі), або функціональну область (навіть якщо вона використовується в блоці), і коли використовується в глобальному масштабі, створює властивість глобального об'єкта.
  • Дивіться мої "три корисні речі" вище, всі вони стосуються цього питання.

1

Семантика varтаlet

varі letє заявою для машини та інших програмістів:

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

Наслідки використання varтаlet

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

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

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

Коли використовувати const

Якщо значення посилання не змінюється в ході виконання, правильним синтаксисом для вираження наміру програміста є const. Для об'єктів зміна значення посилання означає вказівку на інший об'єкт, оскільки посилання є незмінним, але об'єкт - ні.

" const" об'єкти

Для посилань на об'єкт вказівник не може бути змінений на інший об'єкт, але об'єкт, який створений і призначений для constдекларації, може змінюватися. Ви можете додавати або видаляти елементи із constзгаданого масиву та змінювати ключі властивостей на constпосилається об'єкт.

Щоб досягти незмінних об'єктів (що ще більше полегшує міркування коду для людей і машин), ви можете Object.freezeоб'єкт при оголошенні / призначенні / створенні, наприклад:

const Options = Object.freeze(['YES', 'NO'])

Object.freeze впливає на продуктивність, але ваш код, мабуть, повільний з інших причин. Ви хочете профайлювати це.

Ви також можете інкапсулювати змінний об'єкт у машині стану та повернути глибокі копії у вигляді значень (так працюють Redux та React). Див. Уникнення змінного глобального стану в браузері JS для прикладу того, як побудувати це на перших принципах.

Коли varіlet хороший матч

letі varпредставляють змінний стан. На мій погляд, їх слід використовувати лише для моделювання фактичного стану, що змінюється . Такі речі, як " живий зв'язок?" ".

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

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

Більш нюансове пояснення дивіться у розділі " Шунтовий мутант" - "Справа"const .



0

Я не є експертом у галузі компіляції JS, але є сенс сказати, що v8 використовує прапор const

Зазвичай після оголошення та зміни купи змінних, пам'ять роздроблена, і v8 зупиняється на виконанні, робить паузу на кілька секунд, щоб зробити gc або збирати сміття.

якщо змінна оголошена const v8, можна впевнено помістити її в щільний контейнер фіксованого розміру між іншими змінними const, оскільки вона ніколи не зміниться. Він також може зберегти належні операції для цих типів даних, оскільки тип не зміниться.


0

Якщо мова йде про рішення між let і const , завжди віддайте перевагу const, щоб використання в коді було зрозумілим. Таким чином, якщо ви спробуєте передекларувати змінну, ви отримаєте помилку. Якщо немає іншого вибору, крім того, щоб передекларувати його, просто перемкніть на " хай" . Зауважте, що, як каже Ентоні , значення не є незмінними (наприклад, об’єкт const може мати властивості, що мутуються).

Що стосується var , оскільки ES6 не працює, я ніколи не використовував його у виробничому коді і не можу придумати для нього випадок використання. Тим не менш, будьте обережні, що змінні, оголошені з var , не мають області блоку.

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