ES6で「let」と「const」をどれくらい使用する必要がありますか?


214

最近、io.js用のES6コードをたくさん書いています。学ぶべきコードはそれほど多くないので、自分の慣習を定義しながら進めているように感じます。

私の質問はどのような場合に使用する程度であるconstlet

私はこのルールを適用しています:可能であれば、を使用しますconstlet値を変更する必要があることがわかっている場合にのみ使用してください。(後で値を変更する必要があることが判明しconstlet場合は、いつでも戻ってa に変更できます。)

この規則の主な理由は、一貫して簡単に適用できることです。灰色の領域はありません。

問題は、このルールを適用すると、実際には宣言の95%がになるということですconst。そして、これは私には奇妙に見えます。私は使用していますletのようなもののためにiではforループ、または時折(実際の生活の中で多くを起動しない)の累積フィボナッチ合計のようなもののために。これには驚きました。これまでのES5コードの「変数」の95%は、変化しない値に対するものでした。しかしconst、コード全体を見ると、どうも間違っているように感じます。

だから私の質問は次のとおりconstです。これだけ使用しても大丈夫ですか?私は本当に次のようなことをすべきconst foo = function () {...};ですか?

またはconst、モジュールの最上部にリテラルをハードコーディングしているような状況、つまりフルキャップで行うような状況のために予約する必要がありますconst MARGIN_WIDTH = 410;か?


7
この質問は主に意見に基づくものであり、したがってクローズされる可能性が高いと思いますが、私の2セントはconstこれだけ使用しても構いません。
ジョミナル

15
function foo() {...}より良い<anything> foo = function() {...}
-OrangeDog

12
@OrangeDog私はその反対を正確に結論付けたので、それについてのあなたの説明を見たいです。function foo() {...}巻き上げのため、デバッグ時に軽度の混乱を引き起こす可能性がある警告があります。また、その存在は、同じことを行う2つの構造がありますが、そのうちの1つは非常に特定のコンテキストでのみ機能することを意味します。(式が存在できる場所であればどこでも関数式を使用できますが、ステートメントレベルでのみ関数宣言を使用できます。)簡潔にしたい場合、問題は単に関数式の構文が単語全体を使用することですfunction
キーン

11
スタックトレースには、anonの代わりに関数の名前が付けられます。ホイストは優れているため、fooが未定義であることを心配することなく、自然な順序で関数を定義できます。
OrangeDog

1
これらは心に留めておくべき良い点ですが、私はまだ確信していません。最新のデバッガーは、割り当てられているシンボルに基づいて、関数に適切な表示名を選択します(存在する場合-名前がない場合は、名前付き関数式を使用できます)。関数宣言の自然な順序は非常に主観的です。自然な順序は、基本的なピースを定義することから始めて、後でそれらを使用するピースを定義することだと考えるのが合理的かもしれません。
キーン

回答:


183

ここでの私の返信はjavascript固有ではありません。

半簡単な方法でそれを可能にするすべての言語の経験則として、可能な場合は常にconst / final / readonly /何でもあなたの言語で呼び出されるものを使用すると言います。理由は簡単です。変更できるものと変更できないものが明らかな場合、コードについて推論するのがはるかに簡単です。さらにこれに加えて、多くの言語では、constとして宣言した変数に誤って割り当てたときに何か間違ったことをしていることを知らせるツールサポートを利用できます。

戻ってconstをletに変更するのは簡単です。そして、デフォルトでconstを実行すると、そうする前によく考えます。そして、これは多くの場合良いことです。

変数が予期せずに変化するというバグを見たことがありますか?たくさん推測します。私が目にするバグの大部分は、予期しない状態の変化を伴うことを知っています。constを自由に使用してこれらのバグをすべて取り除くことはできませんが、多くのバグを取り除くことができます!

また、多くの関数型言語には不変の変数があり、デフォルトではすべての変数がconstです。たとえば、ErlangまたはF#を見てください。割り当てなしのコーディングはこれらの言語で完全に機能し、人々が関数型プログラミングを愛する多くの理由の1つです。優れたプログラマーになるためには、これらの言語から状態の管理について多くのことを学ぶ必要があります。

そして、それはすべてconstで非常にリベラルであることから始まります!;)letに比べて書くべき文字が2つだけなので、先に進みましょうconst


45
constlet... よりも2つの文字が多い
-OrangeDog

72
ただし、5文字は不変です。
セラド

7
これはvalScalaでの使用var(変数を不変として宣言する)や、使用できない場合にのみ(可変の同等物)を使用することによく似ていますval。言い換えると、変数をデフォルトで不変として宣言し、絶対に必要な場合にのみ可変性を導入します(単に可変アプローチがよりクリーンであるためかもしれません)。
キャット

7
私はこの答えに同意しますが、プレーンオブジェクトや配列のようなものを操作する場合、プロパティが 'const'で定義されていても変化する可能性があるため、物事はそれほど明白ではないことに留意してください。object.freezeのように動作する「const」を考えていましたが、そうではありません。
バックデスク

2
@Cerad「4文字少ない」という意味ですか、それともここで冗談を逃していますか?
マティアスバインズ16

57

constオブジェクトキーは可変なので注意してください。

ここから:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

オブジェクトキーは保護されていません

この例を考えてみましょう:

const colors = {red: "#f00"}; 
console.log(colors); // { "red": "#f00" }

colors.red = "#00f";
colors.green = "#0f0";
console.log(colors); // { "red": "#00f", "green": "#0f0" }

配列についても同じこと:

const numbers = [1, 2, 3];
console.log(numbers); // [ 1, 2, 3 ]

numbers.push(4);
console.log(numbers); // [ 1, 2, 3, 4 ]

私は完全に自分では決めていませんがconst、すべての非配列/非オブジェクトとletオブジェクト/配列への使用を検討しています。


34
確かに、期待されるIMO-定数は、に割り当てられたオブジェクト参照constです。colors = numbers期待どおりに動作しません。オブジェクトのプロパティを保護する場合は、Object.freeze() developer.mozilla.org
en

16
誤解を招く。不変です。しかし、実際のオブジェクトプロパティはそうではありません。
ガストンサンチェス

1
+1ええ、参照は保護されていますが、質問に関しては、のような場合に使用するのはかなり愚かconst moment = require('moment')です。あなたが誰かがmoment = dead.fish(() => pizza)後でしようとするのを心配しているタイプの人でない限り。
マックスウェル

5
おそらくもっと現実的に心配するmoment = Date.now()。しかし、いずれにせよ、コードが不変式を仮定している場合、可能な限りそれを強制することに何の問題もありません。
ジェームズM.

3
ただし、不変ではないとは誰も言いませんでした。constの目標は、名前が初期化されたオブジェクトとは異なるオブジェクトを参照しないことを本当に保証する場合、それを不変にすることであるというのはよくある誤解です。
モノクローム

25

心配しないでください。constJavaScriptへのすばらしい追加であり、理にかなっているすべての場所で使用することをお勧めします。より堅牢なコードになります。

オブジェクトに関してconstは、変数を再割り当てから保護しますが、不変オブジェクトが必要な場合は、Object.freeze以下のメソッドが必要です。

const immutableOject = Object.freeze({immutableProperty: 'foo'});

const再割り当てからのみ保護され、freezeメソッドはすべての即時プロパティを保護します。すべてのネストされたプロパティも不変にする必要がある場合は、freezeそれらを再帰的に行う必要があります。


14
Object.freeze浅いことに注意してください。
マティアスバイネンズ16

@MathiasBynens私はこのコメントに出くわしました、そして、あなたがそれが何を意味したかについて、私は興味があります。詳しく説明してもらえますか?
コールロバーツ

@ColeRoberts浅い不変性の概念は、オブジェクト参照自体は不変ですが、プロパティは変更できる場合です。constキーワードは浅い不変性のみを行うため、すべてのプロパティも不変である必要がある場合はObject.freezeを使用する必要があります。
clean_coding

3
@ColeRobertsこれは、凍結されたオブジェクト(つまり、ネストされたオブジェクト)内のオブジェクト値を変更できることを意味します。詳細については、mathiasbynens.be / notes / es6-const#immutable-valuesを参照してください。
マティアスバインズ

19

私のES6constでは、不変性に関する投稿ではありませんconst。仕様に正確に一致することを意味します。

これらの客観的な事実に基づいて、個人的な好みを以下に示します。

[...]それは使用することは理にかなってletconstあなたのES6コードに次のように:

  • constデフォルトで使用
  • let再バインド(つまり、任意の形式の再割り当て)が必要な場合にのみ使用します
  • varES6では使用しないでください)

主観的かもしれませんが、これは仕様の意図に最も近いという事実です。

let通常、デフォルトで使用する人は、const変数を定数として扱います(設計上、必ずしもそうではありません!)。それぞれに、しかし、私は意図した目的のために物を使うことを好みます、そして、人々が誤解に基づいてそれに割り当てるいくつかの作り上げの意味のために。

const定数にのみ使用することは、サイドバーのコンテンツにのみHTML <aside>要素を使用することに似ています


2
const一定でないのになぜ名前を付けるのですか?
nu everest

3
@nueverestそれは何のためでconstはないからです。上記を読みましたか?
マティアスバイネンズ16

2
@MathiasBynensの(唯一の?)問題constは、と呼ばれることだと思いますconst。最初は多くの(すべての?)開発者を混乱させる(javascriptの)愚かな名前です。IMO constlet(特にlet短いがconst非常に一般的であるために)let呼び出されていて、何か別の名前が呼び出されていた場合に優れています。
MrN00b

@MathiasBynens私はそれを得るが、なぜそれを呼び出すのですか?このページが示すように、それは大きな混乱を引き起こしています。
jtr13

4

私の個人的なアプローチは、コードの読みやすさと理解を支援するために考えました:


let短命の変数専用で、1行で定義され、その後は変更されません。一般に、入力の量を減らすためだけに存在する変数。例えば:

for (let key in something) {
  /* we could use `something[key]` for this entire block,
     but it would be too much letters and not good for the
     fingers or the eyes, so we use a radically temporary variable
  */
  let value = something[key]
  ...
}

constモジュール全体で一定であることがわかっているすべての名前。ローカルに一定の値は含まれません。value上記の例では、例えば、その範囲内で一定であるとして宣言することができconstますが、多くの反復があるので、それぞれ1に同じで価値があります名前の思考の中に読者をだましことができ、「値」は、value常に同じ。モジュールと関数は、const変数の最良の例です。

const PouchDB = require('pouchdb')
const instantiateDB = function () {}
const codes = {
  23: 'atc',
  43: 'qwx',
  77: 'oxi'
}

var変動する可能性のあるものとそうでないものすべてに。ローカルで定数であり、適切ではないlet(つまり、単純な直接宣言では完成しない)場合でも、コードを読む人を混乱させる可能性のある名前は、で宣言されることに適用されますvar。例えば:

var output = '\n'
lines.forEach(line => {
  output += '  '
  output += line.trim()
  output += '\n'
})
output += '\n---'

for (let parent in parents) {
  var definitions = {}
  definitions.name = getName(parent)
  definitions.config = {}
  definitions.parent = parent
}

さらなる解説と今後の更新の可能性はこちら


10
2番目のコードスニペットは銃のように見えます。
ジュリアン

1

JavaScriptは、変数が関数などになる可能性があるという点で少し特別ですが、C#、Java、または別の同様のCスタイル言語で検討してください。

const public void DoSomething()

これconstは奇妙なことです。なぜなら、これらの言語のメソッド宣言は、他の言語にコンパイルされた後は変更できないからです。

なぜJavaScriptは違うのでしょうか?したがって、コンパイルされませんが、それはコンパイラが提供できる安全性を捨てるべきだという意味ではありません。constキーワードを使用すると、より安全になり、確実なアプリケーションになります。

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