web-dev-qa-db-ja.com

JavaScriptで関数を定義するためのconstの適切な使用

JavaScriptでconstを使用して設定できる値の種類、特に関数に制限があるかどうかに興味があります。これは有効ですか?それがうまくいくことは確かだが、それは何らかの理由で悪い習慣と考えられているか?

const doSomething = () => {
   ...
}

ES6ではすべての機能をこのように定義する必要がありますか?もしそうなら、これがつかまったようには見えません。

コメントをありがとう!

119
David Sinclair

行ったことに問題はありませんが、関数宣言と関数式の違いを覚えておく必要があります。

関数宣言、つまり、

function doSomething () {}

スコープの先頭に完全に吊り下げられています(そしてletconstのように、それらはブロックスコープです)。

これは、以下がうまくいくことを意味します。

doSomething() // works!
function doSomething() {}

関数式、つまり、

[const | let | var] = function () {} (or () =>

無名関数(function () {})の作成と変数の作成、そしてその無名関数のその変数への代入です。

そのため、スコープ内での変数の持ち上げに関する通常の規則 - ブロックスコープの変数(letおよびconst)は、ブロックスコープの先頭にundefinedとして巻き上げられません。

これの意味は:

if (true) {
    doSomething() // will fail
    const doSomething = function () {}
}

doSomethingが定義されていないので失敗します。 (ReferenceErrorがスローされます)

varを使用するように変更した場合は、変数のホイストが発生しますが、undefinedに初期化されるため、上記のコードブロックは機能しません。 (TypeErrorは呼び出し時の関数ではないため、これはdoSomethingをスローします)

標準的なやり方では、仕事に適したツールを常に使用する必要があります。

Axel Rauschmayerは、es6のセマンティクスを含むスコープと巻き上げについての素晴らしい投稿をしています。 ES6における変数とスコープ

168
tkone

constを使って関数を定義することはハックのように思えますが、それを優れたものにする大きな利点がいくつかあります(私の意見では)

  1. それは関数を不変にするので、その関数が他のコードによって変更されることを心配する必要はありません。

  2. 太い矢印のシンタックスを使うことができます。

  3. 矢印関数を使うことはあなたのためにthisバインディングを世話します。

functionの例

// define a function
function add(x, y) { return x + y; }

// use it
console.log(add(1, 2)); // 3

// oops, someone mutated your function
add = function (x, y) { return x - y; };

// now this is not what you expected
console.log(add(1, 2)); // -1

constと同じ例

// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;

// use it
console.log(add(1, 2)); // 3

// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged
61
Gaafar

この質問が出されてから3年が経ちましたが、私は今それに出くわしています。この答えははるかに下回っているので、それを繰り返してください。

Q:JavaScriptのconstを使って設定できる値の種類、特に関数に制限があるかどうか興味があります。これは有効ですか?それはうまくいきますが、それは何らかの理由で悪い習慣だと考えられますか?

明白な理由や利点がない場合でも、constfunctionsステートメントを使用している多くのJavaScriptコーダー常にを観察した後、私はいくつかの研究をしたいと思いました。

"なんらかの理由で悪い習慣と考えられますか?"に対する答えとして、IMO、そうです、あるいは少なくともfunctionステートメントを使用することには利点があります。

これは主に好みとスタイルの問題であるように思われます。上記でいくつかの良い議論がありますが、この記事で行われているほど明確なものはありません。

常に混乱している:まだJavaScriptの関数ステートメントを使用している理由 by medium.freecodecamp.org/Bill Sourour、 JavaScriptの達人、コンサルタント、そして先生。

あなたがすでに決断をしたとしても、私は皆にその記事を読むように勧めます。

これが主なポイントです:

関数ステートメントは、[const]関数式に比べて2つの明らかな利点があります。

利点1:意図の明確さ

1日に何千行ものコードをスキャンする場合、プログラマの意図をできるだけ迅速かつ簡単に把握できると便利です。

利点#2:宣言の順序==実行の順序

理想的には、コードが実行されると予想される順序で、多かれ少なかれコードを宣言したいと思います。

これは私にとってはお勧めです。constキーワードを使用して宣言された値は、実行が到達するまでアクセスできません。

先ほど説明したことにより、逆さまに見えるコードを書くことを強いられます。私たちは最低レベルの機能から始めて、私たちのやり方で努力しなければなりません。

私の脳はそのように機能しません。詳細の前にコンテキストが欲しいのですが。

ほとんどのコードは人間によって書かれています。したがって、ほとんどの人の理解の順序が大部分のコードの実行の順序にほぼ従うことは理にかなっています。

12
JMichaelTX

constを使用することには非常に重要な利点がいくつかあります。また、意図的であることを示すために、可能な限り使用することをお勧めします。

私が言うことができる限りでは、それはJavaScriptにおける変数の最も指示的で予測可能な宣言であり、そしてそれがいかに制約されているかの最も有用なものの一つです。どうして? varおよびletの宣言に使用可能ないくつかの可能性を排除するためです。

constを読んだときに何が推測できますか? const宣言ステートメントを読んで、その変数への他の参照をスキャンせずに、次のことをすべて知っているでしょう。

  • 値はその変数にバインドされます(ただし、その基礎となるオブジェクトは深く不変ではありません)。
  • すぐに含まれているブロックの外からはアクセスできません
  • tDZ(Temporal Dead Zone)規則により、バインディングは宣言前にアクセスされることはありません。

次の引用は、letconstの利点を主張する 記事 からの引用です。また、キーワードの制約/制限に関するあなたの質問にも直接答えます。

letconstで提供されているような制約は、コードを理解しやすくするための強力な方法です。あなたが書くコードの中でこれらの制約のできるだけ多くを生むようにしてください。コードの意味を制限する宣言的な制約が多いほど、将来的に人間がコードを読み、解析し、理解するのがより簡単かつ迅速になります。

確かに、const宣言にはvar宣言よりも多くの規則があります。ブロックスコープ、TDZ、宣言時の代入、再割り当てなし。 varステートメントは関数スコープを通知するだけです。ただし、ルールカウンティングでは多くの洞察が得られません。複雑さの観点からこれらのルールを比較検討することをお勧めします。ルールは複雑さを増すか減らすかconstの場合、ブロックスコープは関数スコープよりも狭いスコープを意味し、TDZは宣言の前に使用方法を見つけるためにスコープをスコープから逆方向にスキャンする必要がないことを意味します。同じ参照。

ステートメントの制約が多いほど、コードは簡単になります。ステートメントの意味するところに制約を加えると、コードは予測不可能になります。これが、静的型付きプログラムが一般的に動的型付きプログラムよりも読みやすくなる最大の理由の1つです。静的型付けはプログラム作成者に大きな制約を課しますが、プログラムの解釈方法にも大きな制約を課し、そのコードを理解しやすくします。

これらの議論を念頭に置いて、可能な限りconstを使用することをお勧めします。これは、考えられる可能性が最も少ないステートメントであるためです。

出典: https://ponyfoo.com/articles/var-let-const

6
mrmaclean89