質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
ESLint

ESLintは、JavaScriptのための構文チェックツール。全検証ルールを自由に on/offでき、独自のプロジェクトに合わせたカスタムルールを容易に設定することが可能。公開されている様々なプラグインを組み込んで使用することもできます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

493閲覧

JavaScriptのconstについて

退会済みユーザー

退会済みユーザー

総合スコア0

ESLint

ESLintは、JavaScriptのための構文チェックツール。全検証ルールを自由に on/offでき、独自のプロジェクトに合わせたカスタムルールを容易に設定することが可能。公開されている様々なプラグインを組み込んで使用することもできます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

2クリップ

投稿2017/09/10 02:00

編集2017/09/10 08:03

JavaScript

1 let obj = { id: 3 }; 2 obj.id = 4; //変更を加える

上記のコードですと、ESLintに「objは再代入されてないんだからconst使え!」と、
「prefer-const」にESLintのチェックに引っかかります。

JavaScriptのconstは他の言語とちょっと意味合いが違うのかもしれませんが、
上記のようなケースにおいて、JS使いの方はconst使いますか? 使った方が適切ですか?

補足

let scale = d3.scaleLinear(); console.log(scale.domain()); // ▶︎(2) [0, 1] scale.domain([0, 100]); //変更を加える console.log(scale.domain()); // ▶︎(2) [0, 100]

同じく、こういうのも「const使え!」とESLintに言われます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

const は「変数の再代入を避ける」為に使います。
一方、質問者さんは「プロパティの再代入を避けられないこと」を考慮されていますが、これは別の問題です。

  • 「変数の再代入を避ける」為に const を使う
  • 「プロパティの再代入を避ける」為に Object.freeze() を使う

個別のプロパティ再代入を制御する場合は Object.create(), Object.defineProperty() を使います。

Re: hayatomo さん

投稿2017/09/10 03:28

think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/09/10 03:36

``` const obj = {id: 3}; // obj.id = 5; ``` 再代入は以降されないことをconstにより明示。ただし、オブジェクト内の値が変わるかどうかについては不明。 ``` const obj = {id: 3}; Object.freeze(obj); // obj.id = 5; //エラー ``` 再代入は以降されないことをconstにより明示。かつ、Object.freeze()をconst宣言直下でわかりやすく使うことで、オブジェクト内の値も不変であることを明示。
退会済みユーザー

退会済みユーザー

2017/09/10 03:37

つまり、再代入が以降ないものに関してはconst使って、Object.freeze()がconst直下にない場合は、以降、オブジェクトの値は変わるかもしれないということを明示するみたいな感じでやってけばいいんですかね〜。
退会済みユーザー

退会済みユーザー

2017/09/10 05:42

freezeはnestされたobjectの場合、子のobjectまでは凍結されないみたいですね。カスタムメソッド作んないといけないのか。。
miyabi-sun

2017/09/10 06:21

Object.freezeはその弱点があるから駄目な子なんだよね。 JavaScriptは潔癖になると制御コードだらけですぐ汚くなるから、ソースコードは簡素にまとめておいて運用ルールで頑張る言語だと思うよ。 完全に縛るならElm-LangやPureScript、Scala.jsみたいなAltJS使った方が良いと思う。
think49

2017/09/10 08:26 編集

> 再代入が以降ないものに関してはconst使って、Object.freeze()がconst直下にない場合は、以降、オブジェクトの値は変わるかもしれないということを明示するみたいな感じでやってけばいいんですかね〜。 わたしの場合、間違った使い方が出来ないように制限を設けるイメージで明示するとは少し違いますね。 コードの意味が分かっている人であれば、constを使っていても使っていなくても、再代入されることで処理が破綻する事が分かるはずで、どちらかといえばこの手の強制力のある制限は「コードが分からない人向け」だと思っています。 勿論、分かる人にはよりわかりやすくなるメリットはあります。 > freezeはnestされたobjectの場合、子のobjectまでは凍結されないみたいですね JavaScriptはプロトタイプベースの言語ですが、nestされたオブジェクトのどこまでを影響範囲とするかが規定しづらい言語だと感じます。 Node#CloneNodeではDOM APIの範疇でディープコピーするわけですが、Object.freezeがnestされたオブジェクトに対応するオプションがあったとして、 - 同じ [[Prototype]] である限り、階層をまたいで参照するのか、全てのオブジェクトのプロパティを参照するのか - [[]Prototype]] 上に存在するプロパティも参照するのか という課題があります。 --- Object.assignのディープコピー化にも同様の課題があり、更には、 - コピーする対象の [[]Prototype]] までコピーするのか - コピーする対象の内部スロットまでコピーするのか という課題もあります。 例えば、プロパティにnew WeakMapやnew Dateが存在した場合、同じ性質でかつ内部データまで同じでなければ使う意味がないですよね。 しかし、内部スロットは他からはアクセスされない不可侵領域であるべきであって、内部スロットまでコピーされるのは問題です。 [], {} のネスト構造で考えると現行仕様に不満も出てくると思いますが、汎用的な仕様として考えると、その希望に応えるのは難しいものがあるのではないかと思います。 プリミティブ値の集合体としての役割であるなら、JSONを利用し、そうでなければコピーする基準を定義してから、自身で実装する事になります。
guest

0

prefer-const を ESLint に入れている場合は「再代入しない変数」に関しては極力 const を使うように指摘されます。

ここから先は let がいいか const がいいかという議論ですが、 let にした所で大差はない一方で、 prefer-const を利用している一般的なプロダクトでは、 const 以外の変数にすることを極力避けます。

これは const を使う方が 「この変数はこれから再代入されることはない」 という認識を持ってプログラムを書くことができるからで、逆に letvar を使ってる場合は 「再代入されることがある特殊な変数なんだ」 というマーカーとして扱うことができるからです。

JavaScript ではありませんが、 Java の名著である Effective Java には「可変性を最小限にするべし」
というメッセージがあります。

http://hjm333.hatenablog.com/entry/2015/09/15/000644

これに倣ってなるべく let ではなく、 const を書く事を推奨する文化が生まれています。

ただし、 JavaScript は const にした所で、オブジェクトのプロパティフィールドには代入可能ですし、完璧な不変性を保つことはできません。そういう不変性を推奨する言語(Java, Scala, Haskell)からの書き方を多少なりとも輸入し、今時点では自分の観測範囲では let で書くよりも const で書く方が推奨されていると思います。

投稿2017/09/10 02:47

yosuke_furukawa

総合スコア390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/09/10 02:56

あ、すみません。質問の趣旨が不明確でした。。。「JavaScript は const にした所で、オブジェクトのプロパティフィールドには代入可能ですし、完璧な不変性を保つことはできません。」という話をふまえた上で、質問に掲載したようなコードの場合でも、const使うべきなのかなといった趣旨の質問となります。const使えば、以降のコードでその変数に再代入はされないってことは明確になるけど、オブジェクトのプロパティーに対する値は変わったりするから、逆に混乱のもとになりそうな気がしまして。
yosuke_furukawa

2017/09/10 05:09

> オブジェクトのプロパティーに対する値は変わったりするから、逆に混乱のもとになりそうな気がしまして。 これを気にするのであれば「constという変数宣言が誤解のもとになるからやめよう」というルールになり、「let」 を基本にすることになると思います。 ただ実際には「変数宣言時にオブジェクトを不変にできる」という言語は多くないので、自分の感想としてはそこまで混乱の元にならないと思っています。 Java の final しかり、 Scala の val しかり、宣言しただけで再代入禁止になるものの、不変にはなりません。 自分が何かしら言語を教えるときには「不変」と「再代入禁止」を分けて考えた方が良いと教えています。 その上でJavaScriptで ESLint を使った場合に `prefer-const` にしただけでは「不変」ではない事も教えていますが、僕は `prefer-const` にするように推奨しています。 理由は前に書いたとおりですが、「完全なる不変性が保たれないから(100%の安全を担保できないから)」といって、「再代入可能にして可変性を増やすべきではない(危険性を増やすべきではない)」という理由です。
退会済みユーザー

退会済みユーザー

2017/09/10 05:45

constは再代入不可という意味であることを頭に叩き込んで、その意味の為だけにconstを使っていこうと思います。
guest

0

まぁ、作ったオブジェクトを後からごちゃごちゃ弄るなって話だね。
ライブラリや組み込みメソッドがバリバリなJavaScriptでは現実的にはかなり難問なんだけどね…

JavaScript関数型プログラミング 複雑性を抑える発想と実践法を学ぶ の本では、
オブジェクトにする場合は、毎回自分自身をnewし直して値を更新出来るように備えようというアプローチが書いてあったね。

単純なObjectでやりたいならこんな感じのアプローチ。

JavaScript

1const obj = {id: 3}; 2const obj2 = Object.assign({}, obj, {id: 4}) 3 4console.log(obj); 5// {id: 3} 6console.lo(obj2); 7// {id: 4}

後者の質問だけど、そのd3.scaleTime.rangeは破壊的なメソッドなのかな?
d3に関しては使った事無いからよく分からないけど、
サンプルを軽く眺めた限り、jQueryと同じパターン※で非破壊的な作りだと思うんだよね。

もし破壊的じゃないなら、rangeメソッドいくら叩いてもオブジェクトの値は変更されない。
つまりconstの方が適切だよね、一回確認してみてくれる?

※jQueryのパターン
毎回thisを返しまくって、メソッドチェーンを実現している。
途中の結果を何時でも変数に入れてキャッシュ出来るように、各メソッドは毎回新しいインスタンスを作り直している。

投稿2017/09/10 03:36

編集2017/09/10 03:56
miyabi-sun

総合スコア21145

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/09/10 04:24

``` let scale = d3.scaleLinear(); console.log(scale.domain()); // ▶︎(2) [0, 1] let scale2 = scale.domain([0, 100]); console.log(scale.domain()); // ▶︎(2) [0, 100] console.log(scale2.domain()); // ▶︎(2) [0, 100] ```
退会済みユーザー

退会済みユーザー

2017/09/10 04:25 編集

d3には破壊的メソッドもあれば、非破壊的メソッドもあります。上記コードは破壊的メソッドと言って良いのですよね?
退会済みユーザー

退会済みユーザー

2017/09/10 04:30 編集

> const obj2 = Object.assign({}, obj, {id: 4}) 既存のオブジェクトに変更を加えたい場合は、immutable意識するってことに徹すれば、あとは、単純に再代入出来ないって意味だけのconstを気にせず使えば良いのかもしれませんね。 JS関数型プログラミングの本は2冊書いましたが、絶賛積読中です!掲載いただいた新書は注文してないですが、かいたい。。。
miyabi-sun

2017/09/10 05:56

これは破壊的だね、イケてないなぁ…
退会済みユーザー

退会済みユーザー

2017/09/10 06:33

前にdeep copyできてなかったオブジェクトをd3に渡して激ハマりしました。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問