Const в 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/…
Себастьен С.

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-компилятор. Может быть, «использовать строгий» режим тоже имеет значение.
Руди

9
@Rudie Функция, которую вы ищете, называется замораживанием объекта. constпросто предотвращает переназначение «переменной» на другое значение. const a = {}; a = {};выдаст ошибку в строгом режиме.
Тибос

Обычно я использую const вместо let для большинства переменных, так же как в Java я добавляю final для большинства объявлений переменных.
кодирование

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 иначе, чем к var. Я думаю, что @Tibos прояснил это.
AxDG

Джеймс, спасибо за указание на аспект поддержки. imho все ответы на JavaScript должны включать разбивку поддержки браузера. хорошо объяснил
Хабсон Бропа

4
Примечание. В августе 2014 года функция ES6 была заморожена. В июле 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был видоизменен через знак равенства.
Чарви

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 Спасибо! Ваш ответ привел меня к «передача по значению против передачи по ссылке», новая концепция, и странная - где изменение значения ≠ переназначение. Любой, кто нуждается в дополнительном объяснении, должен проверить ответы здесь: 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 To

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

Использование const очень похоже на модификаторы доступа, истинная неизменность не является целью.
StingyJack 30.09.16

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вами всегда будет предполагаться, что pi будет 3,14 [...], это факт.

Если вы определите его как 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 является областью видимости блоков, как и let, которая не совпадает с var (которая находится в области функций)

Короче говоря, когда что-то вряд ли изменится при повторном назначении, используйте const, иначе используйте let или var в зависимости от области, которую вы хотели бы иметь.

Гораздо проще рассуждать о коде, когда он абсолютно очевиден, что можно изменить с помощью переназначения, а что нельзя. Изменить const на let очень просто. И если по умолчанию использовать const, вам придется дважды подумать, прежде чем делать это. И это во многих случаях хорошо.


2

Он обеспечивает: 1) постоянную ссылку, например, const x = [] - массив можно изменить, но x не может указывать на другой массив; и 2) блокировать область видимости. const и let вместе заменят 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;
}

В вышеприведенных примерах обе функции дают разные результаты, но с одним и тем же именем переменных. Здесь мы видим, что 'process' & 'result' оба используются как переменные, и они должны быть.

 **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представляют изменяемое состояние. Они должны, на мой взгляд, использоваться только для моделирования фактического изменчивого состояния . Такие вещи, как « жива ли связь? ».

Они лучше всего инкапсулированы в тестируемых конечных автоматах, которые предоставляют постоянные значения, которые представляют « текущее состояние соединения », которое является константой в любой момент времени, и что на самом деле интересует остальная часть вашего кода.

Программирование уже достаточно сложное с составлением побочных эффектов и преобразованием данных. Превращение каждой функции в непроверяемый конечный автомат путем создания изменяемого состояния с переменными просто накапливает сложность.

Для более подробного объяснения см. Shun the Mutant - Дело заconst .



0

Я не эксперт в области компиляции JS, но есть смысл сказать, что v8 использует флаг const

Обычно после объявления и изменения группы переменных память фрагментируется, и v8 останавливается для выполнения, делает паузу на несколько секунд, чтобы сделать gc или сборщик мусора.

если переменная объявлена ​​с помощью const v8, можно с уверенностью поместить ее в жесткий контейнер фиксированного размера между другими переменными const, поскольку она никогда не изменится Он также может сохранить правильные операции для этих типов данных, так как тип не изменится.


0

Когда дело доходит до решения между let и const , всегда предпочитайте const, чтобы использование было понятно в коде. Таким образом, если вы попытаетесь переопределить переменную, вы получите ошибку. Если нет другого выбора, кроме как изменить его, просто переключитесь на let . Обратите внимание, что, как говорит Энтони , значения не являются неизменяемыми (например, у объекта const свойства могут изменяться).

Когда дело доходит до var , поскольку ES6 отсутствует, я никогда не использовал его в производственном коде и не могу придумать какой-либо вариант его использования. Однако следует помнить, что переменные, объявленные с помощью var , не имеют области видимости блока.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.