JavaScriptでのconst:いつそれを使用し、それは必要ですか?


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/...
セバスチャン・C.

回答:


462

質問には2つの側面があります。const代わりにを使用することの技術的な側面と、それを使用するvarことに関する人間関連の側面は何ですか。

技術的な違いは重要です。コンパイルされた言語では、定数はコンパイル時に置き換えられ、その使用により、デッドコードの削除などの他の最適化が可能になり、コードの実行時効率がさらに向上します。最近の(あまり使われていない)JavaScriptエンジンは実際にJSコードをコンパイルしてパフォーマンスを向上させているため、constキーワードを使用すると、上記の最適化が可能であり、実行する必要があることが通知されます。これにより、パフォーマンスが向上します。

人間関連の側面は、キーワードのセマンティクスについてです。変数は、変更が予想される情報を含むデータ構造です。定数は、決して変更されない情報を含むデータ構造です。エラーの余地がある場合は、var常に使用する必要があります。ただし、プログラムの存続期間中に決して変更されないすべての情報をで宣言する必要はありませんconst。異なる状況で情報を変更する必要があるvar場合は、実際の変更がコードに表示されない場合でも、を使用してそれを示します。


4
乾杯、私はMozilla / Googleが理由もなくJSエンジンにconstサポートを追加しなかったと思いました。該当する場合は、必ずconstを使用します。
axdg 2014年

6
constオブジェクトは変更可能であるように見えるので、JSコンパイラが実際にどれほど厳密かはわかりません。多分「厳密な使用」モードも違いがあります。
Rudie、2015年

9
@Rudie探している機能は、オブジェクトの凍結と呼ばれます。const「変数」が別の値に再割り当てされるのを防ぐだけです。const a = {}; a = {};ストリクトモードでエラーをスローします。
Tibos、2015年

ほとんどの変数に対してletの代わりに一般的にconstを使用します。Javaの場合と同様に、ほとんどの変数宣言にfinalを追加します。
コーディング

2
If there is room for error, var should always be used。ESLintなどのツールがすぐにconst違反を指して、今日ではこれは当てはまりません。
vitaly-t 2017

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で宣言された変数など)。

次に、次のように言います。

constECMAScript 6で定義されますが、セマンティクスは異なります。letステートメントで宣言された変数と同様に、constで宣言された定数はブロックスコープになります。

使用するconst場合は、少し古いブラウザをサポートするための回避策を追加する必要があります。


6
素晴らしい答え-MDNに関する記事はもう読みましたが。私が言ったように、私はV8が実際にconstをvarとは異なる方法で実際に扱うかどうかにもっと興味を持っていました。@Tibosはそれをクリアしたと思います。
axdg 2014年

Jamesはサポートの側面を指摘してくれてありがとう。imhoすべてのJavaScriptの回答には、ブラウザーサポートの内訳が含まれている必要があります。うまく説明された
ハブソンブローパ2015

4
注ES6は、2014年8月に機能凍結を受けました。2015年7月に、標準が正式にリリースされました。これを今読んでいる場合、コードが最新のエンジンで管理されている場合は、概説されている承認された回答に従う必要があることを意味します。
FilipDupanović2015年

OPの質問には、特定のNode.jsされる
NICU Surdu

@NicolaeSurdu確かに。それは2014年1月からもですので、おそらくほとんどが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クラウダー2017

const配列のコンテキストで理解しようとしているため、ここに移動しました(使用されている@chharveyの例と同様)。以下の場合のたびに再割り当てされます。なぜ使用していませんか?const countArray = countup(n - 1); countArray.push(n);constconstvar
YCode

1
@YCodeいいえ。を使用するとconst countArray、再割り当てされることはありません。配列にプッシュすることもできます。これにより、メンバーと長さが変更されますが、それを再割り当てとは呼びません。のconst代わりに、letまたはvar再割り当てを防止したい場合に使用します。ところで、再割り当てを許可たい場合letは、ほとんどの場合、より優れていvarます。
チャーベイ

@chharveyありがとう!あなたの返答は私に「値渡しvs参照渡し」という新しい概念、そして奇妙なもの、つまり値の変更≠再割り当てにつながりました。詳細な説明が必要な場合は、こちらの回答を確認してください: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

定数の値も変更してみる例が必要です。
Joshua Pinter 2016年

constの使用はアクセス修飾子と非常によく似ており、真の不変性は目標ではありません。
StingyJack

32

const不変ではありません

MDNから:

const宣言は、値への読み取り専用の参照を作成します。それが保持する値が不変であることを意味するのではなく、変数識別子を再割り当てできないということだけです。


24
しかし、それは少し誤解を招くものです。数値、文字列、ブールなど(プリミティブ)constは不変です。オブジェクトと配列の場合は再割り当てできませんが、内容は変更できます(例:array.push)。
Florian Wendelborn 2017年

2
ただし、JSプリミティブは常に不変です。使用してconstもしなくてもかまいません。
12Me21 '15年

1
したがって、@ Dodekeractは定義上不変ではありません。値を変更できる場合、それは不変ではありませんが、リストしたプリミティブに対して不変として機能します
Anthony

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

後で実行するときに変更される可能性があると思われる場合は、を使用してくださいvar

この例に基づく実際的な違いは、constpiが常に3.14 [...]であると常に想定していることです。これは事実です。

として定義すると、var3.14 [...]になるかどうかにかかわらず、

より技術的な答えについては、@ Tibosは学問的に正しいです。


7

私の経験では、ハードコーディングされたビット(ファイルパスやサーバー名など)を探すコードを探し回る必要なしに、後で変更したいものを設定したいときにconstを使用します。

テストのエラーは別のものですが、xという別の変数を作成する必要があります。これはより正確なテストになります。

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

9
私はあなたの意味を理解しますが、あなたにとって「一定」が「私が変えたいかもしれないもの」を意味するのはおかしいです。:P
Venryx 2017

4

本当に個人的な好み。あなたが言うように、あなたがそれが再割り当てされず、そして一定であるとき、あなたはconstを使うことができました。たとえば、誕生日を割り当てたい場合などです。誕生日が変わることはないので、定数として使用できます。しかし、あなたの年齢は変化するので、それは変数である可能性があります。


17
これは非常に長時間実行されるスクリプトです。
nullability

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 (関数スコープ)とは異なるletと同様にブロックスコープであることに注意してください。

何かがありそうにない場合要するに、再割り当てによる変化を利用constの他の使用はしましょうvarはあなたが持っているしたい範囲に応じました。

再割り当てを通じて何が変更可能で何が不可能であるかが明確である場合、コードについて推論する方がはるかに簡単です。constをletに変更するのはとても簡単です。そして、デフォルトでconstになると、そうする前によく考えます。そして、これは多くの場合良いことです。



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つの結果を生成していますが、同じ名前の変数を使用しています。ここでは、「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;
}

JavaScriptで「let」を使用する前に、jsファイルの先頭に「use strict」を追加する必要があります

 **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(共有するスコープの改善以外の)3つの便利な点let

  • 値を変更してはならないことを後でコードを読む人のために文書化します。
  • これは、あなた(またはあなたの後に来る人)が意図的に戻って宣言を変更しない限り、値を変更できないようにします。
  • それはJavaScriptエンジンに最適化の観点からの分析を保存するかもしれません。たとえば、値を変更できないことを宣言したので、エンジンは値が変更されたかどうかを判断する作業を行う必要がなく、変更されていない値に基づいて最適化するかどうかを判断できます。

あなたの質問:

const代わりにvarいつ使用するのが適切ですか?

値が変更されない変数を宣言しているときはいつでもそれ行うことができます。適切だと考えるかどうかは、完全にあなたの好み/チームの好みにかかっています。

再割り当てされない変数が宣言されるたびに使用する必要がありますか?

それはあなた/あなたのチーム次第です。

var is used in place ofconst`またはその逆の場合、実際に違いはありますか?

はい:

  • varconst異なるスコープルールがあります。(letではなくと比較したかったかもしれませんvar。)具体的に:constletブロックスコープであり、グローバルスコープで使用する場合、グローバルオブジェクトにプロパティを作成しないでください(グローバルを作成する場合でも)。varグローバルスコープ(グローバルスコープで使用される場合)または関数スコープ(ブロックで使用される場合でも)を持ち、グローバルスコープで使用される場合、グローバルオブジェクトにプロパティを作成します。
  • 上記の「3つの有用なこと」を参照してください。これらはすべてこの質問に当てはまります。

1

varおよびのセマンティクスlet

varそしてletマシンへと他のプログラマへの文のとおりです。

この割り当ての価値は、実行の過程で変化することを意図しています。この割り当ての最終的な値に依存しないでください。

使用する意味varlet

varそして、let他のプログラマーに、宣言から最終的に使用するまでの間にあるすべてのコードを読み取らせ、プログラムの実行におけるその時点での割り当ての値について推論します。

ESLintおよびその他の言語サービスのマシン推論を弱め、後の割り当てで誤って入力された変数名を検出し、内部スコープが宣言を忘れた外部スコープ変数名のスコープ再利用を弱めます。

また、ランタイムがすべてのコードパスで多くの反復を実行し、最適化する前に、それらが実際に定数であることを検出します。これはバグの検出と開発者の理解可能性ほど問題ではありませんが。

いつ使うか const

参照の値が実行中に変化しない場合、プログラマーの意図を表す正しい構文はconstです。オブジェクトの場合、参照は不変ですが、オブジェクトはそうではないため、参照の値を変更すると、別のオブジェクトを指すことになります。

" const"オブジェクト

オブジェクト参照の場合、ポインターを別のオブジェクトに変更することはできませんが、作成されてconst宣言に割り当てられたオブジェクト変更可能です。const参照される配列の項目を追加または削除したり、const参照されるオブジェクトのプロパティキーを変更したりできます。

不変オブジェクトを実現するために(これもまた、コードを人間やマシンのために推論しやすくします)、次のようObject.freezeにオブジェクトを宣言/割り当て/作成することができます。

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

Object.freezeはパフォーマンスに影響を与えますが、コードはおそらく他の理由で遅くなります。プロファイルしたい。

また、変更可能なオブジェクトをステートマシンにカプセル化し、深いコピーを値として返すこともできます(これがReduxとReactの状態のしくみです)。第一原理からこれを構築する方法の例については、ブラウザJSでの変更可能なグローバル状態の回避を参照してください。

いつvarそしてlet良い試合か

letvar変更可能な状態を表します。私の意見では、これらは実際の変更可能な状態をモデル化するためにのみ使用されるべきです。「接続は生きていますか?」のようなもの。

これらは接続の現在の状態」を表す定数値を公開するテスト可能な状態マシンに最適にカプセル化されます。これは、任意の時点で定数であり、コードの残りの部分が実際に関心を持っているものです。

プログラミングはすでに、副作用の合成とデータの変換で十分に困難です。変数を含む可変状態を作成することにより、すべての関数をテスト不可能な状態マシンに変換します。

より微妙な説明については、ミュータントの回避-のケースをconst参照してください。



0

私はJSコンパイルビジネスの専門家ではありませんが、v8はconstフラグを利用していると言うのは理にかなっています

通常、一連の変数を宣言して変更した後、メモリは断片化され、v8は実行を停止し、gcまたはガベージコレクションを実行するために数秒の一時停止を行います。

変数がconst v8で宣言されている場合は、他のconst変数間のタイトな固定サイズのコンテナーに入れられると確信できます。また、型が変更されないため、そのデータ型の適切な操作を保存することもできます。


0

letconstの間の決定に関しては、常にconstを優先して、コードでの使用法を明確にします。このようにして、変数を再宣言しようとすると、エラーが発生します。他に選択肢がなく再宣言する場合は、letに切り替えます。Anthonyが言うように、値は不変ではないことに注意してください(たとえば、constオブジェクトは変更されたプロパティを持つことができます)。

それがに来るときVAR ES6が出ているので、私は、生産コードでそれを使ったことがないし、それのためのユースケースを考えることはできません。ただし、varで宣言された変数にはブロックスコープがないことに注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.