Berapa saya harus menggunakan 'let' vs 'const' di ES6?

214

Saya telah menulis banyak kode ES6 untuk io.js baru-baru ini. Tidak ada banyak kode di alam liar untuk dipelajari, jadi saya merasa seperti saya mendefinisikan konvensi saya sendiri ketika saya pergi.

Pertanyaan saya adalah tentang kapan harus menggunakan constvs let.

Saya telah menerapkan aturan ini: Jika memungkinkan, gunakan const. Hanya gunakan letjika Anda tahu nilainya perlu diubah. (Anda selalu dapat kembali dan mengubah constke letjika nanti ternyata Anda perlu mengubah nilainya.)

Alasan utama aturan ini adalah mudah untuk diterapkan secara konsisten. Tidak ada area abu-abu.

Masalahnya adalah, ketika saya menerapkan aturan ini, dalam praktiknya 95% dari deklarasi saya adalah const. Dan ini terlihat aneh bagiku. Saya hanya menggunakan letuntuk hal-hal seperti idalam satu forlingkaran, atau kadang-kadang untuk hal-hal seperti akumulasi total Fibonacci (yang tidak banyak muncul dalam kehidupan nyata). Saya terkejut dengan ini - ternyata 95% dari 'variabel' dalam kode ES5 saya saat ini adalah untuk nilai-nilai yang tidak bervariasi. Tetapi melihat constseluruh kode saya terasa salah.

Jadi pertanyaan saya adalah: apakah boleh menggunakan constsebanyak ini? Haruskah saya benar-benar melakukan hal-hal seperti const foo = function () {...};?

Atau haruskah saya memesan constuntuk situasi-situasi di mana Anda membuat kode literal di bagian atas modul - seperti yang Anda lakukan dengan huruf besar, seperti const MARGIN_WIDTH = 410;?

callum
sumber
7
Saya menduga bahwa pertanyaan ini terutama didasarkan pada pendapat dan dengan demikian kemungkinan akan ditutup, tetapi 2 sen saya: Tidak masalah untuk menggunakan constsebanyak ini.
jhominal
15
function foo() {...}lebih baik dari<anything> foo = function() {...}
OrangeDog
12
@OrangeDog Saya ingin melihat penjelasan Anda untuk itu, karena saya menyimpulkan sebaliknya. Ada peringatan yang function foo() {...}dapat menyebabkan kebingungan kecil saat debugging, karena mengangkat. Juga, keberadaannya berarti kita memiliki dua konstruksi yang melakukan hal yang sama tetapi salah satunya hanya bekerja dalam konteks yang sangat spesifik. (Anda bisa menggunakan ekspresi fungsi di mana pun ekspresi bisa ada, tetapi Anda hanya bisa menggunakan deklarasi fungsi di level pernyataan.) Jika Anda menyukai singkatnya, masalahnya mungkin saja sintaks ekspresi fungsi menggunakan seluruh kata function.
Tertarik
11
Stack traces memiliki nama fungsi bukan anon. Mengangkat itu baik dan mari Anda mendefinisikan fungsi dalam urutan alami, tanpa harus khawatir tentang foo yang tidak terdefinisi.
OrangeDog
1
Itu adalah poin bagus yang ada dalam pikiran, tetapi saya belum yakin. Debugger modern melakukan pekerjaan yang baik untuk memilih nama tampilan yang tepat untuk fungsi Anda berdasarkan simbol apa yang Anda tetapkan (jika ada - jika tidak ada, Anda dapat menggunakan ekspresi fungsi bernama). Urutan deklarasi fungsi alami sangat subyektif. Mungkin masuk akal untuk berpikir bahwa tatanan alami adalah memulai dengan mendefinisikan potongan-potongan dasar, dan kemudian menentukan potongan-potongan yang menggunakannya.
Tertarik

Jawaban:

183

Balasan saya di sini tidak spesifik javascript.

Sebagai aturan praktis dalam bahasa apa pun yang memungkinkan saya melakukannya dengan cara semi-mudah saya akan mengatakan selalu menggunakan const / final / readonly / apa pun namanya dalam bahasa Anda bila memungkinkan. Alasannya sederhana, jauh lebih mudah untuk alasan tentang kode ketika sudah jelas apa yang bisa berubah dan apa yang tidak bisa berubah. Dan selain itu, dalam banyak bahasa Anda bisa mendapatkan dukungan alat yang memberi tahu Anda bahwa Anda melakukan sesuatu yang salah ketika Anda secara tidak sengaja menetapkan ke variabel yang telah Anda nyatakan sebagai const.

Kembali dan mengubah const ke let adalah mati sederhana. Dan menjadi const secara default membuat Anda berpikir dua kali sebelum melakukannya. Dan dalam banyak hal ini adalah hal yang baik.

Berapa banyak bug yang Anda lihat yang melibatkan variabel berubah secara tak terduga? Saya banyak menebak. Saya tahu bahwa sebagian besar bug yang saya lihat melibatkan perubahan status yang tidak terduga. Anda tidak akan menghilangkan semua bug ini dengan bebas menggunakan const, tetapi Anda akan menyingkirkan banyak dari mereka!

Juga, banyak bahasa fungsional memiliki variabel tidak berubah di mana semua variabel adalah konst secara default. Lihatlah Erlang misalnya, atau F #. Pengodean tanpa penugasan bekerja dengan sempurna dalam bahasa-bahasa ini dan merupakan salah satu dari banyak alasan mengapa orang menyukai pemrograman fungsional. Ada banyak yang harus dipelajari dari bahasa-bahasa ini tentang mengelola negara agar menjadi programmer yang lebih baik.

Dan itu semua dimulai dengan menjadi sangat liberal dengan const! ;) Ini hanya dua karakter untuk ditulis dibandingkan dengan membiarkan, jadi lanjutkan dan constsemua hal!

wasatz
sumber
45
constadalah dua karakter lebih dari let...
OrangeDog
72
Tapi 5 karakter kurang dari abadi.
Cerad
7
Ini sepertinya banyak menggunakan valdi Scala (yang mendeklarasikan variabel sebagai tidak dapat diubah) dan hanya menggunakan var(setara yang bisa berubah) ketika kita tidak bisa menggunakan val. Dengan kata lain, kami mendeklarasikan variabel sebagai tidak dapat diubah secara default dan hanya memperkenalkan kemampuan berubah ketika kami benar-benar membutuhkannya (yang mungkin hanya karena pendekatan yang dapat diubah lebih bersih).
Kat
7
Saya setuju dengan jawaban ini tetapi perlu diingat bahwa hal-hal yang tidak begitu jelas ketika bekerja dengan hal-hal seperti benda biasa atau array karena sifat mereka dapat berubah bahkan jika mereka didefinisikan dengan 'const'. Saya telah memikirkan 'const' bekerja seperti object.freeze tapi itu tidak terjadi.
backdesk
2
@Cerad Apakah maksud Anda “kurang dari 4 karakter” atau apakah saya melewatkan beberapa lelucon di sini?
Mathias Bynens
57

Hati-hati, karena constkunci objek bisa berubah.

Dari sini: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

kunci objek tidak terlindungi

pertimbangkan contoh ini:

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

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

Hal yang sama untuk array:

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

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

Saya belum memutuskan sepenuhnya sendiri, tapi saya mempertimbangkan constuntuk menggunakan untuk semua non-array / non-objek dan digunakan letuntuk objek / array.

lax4mike
sumber
34
Benar, tetapi diharapkan IMO - apa yang konstan adalah referensi objek yang ditugaskan untuk Anda const. colors = numberstidak akan bekerja, seperti yang diharapkan. Jika Anda ingin melindungi properti objek Anda, Anda dapat menggunakan Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Josef Engelfrost
16
Menyesatkan. Itu tidak bisa dipungkiri. Tetapi properti objek sebenarnya tidak.
Gaston Sanchez
1
+1 Ya, referensi terlindungi, tetapi dalam hal pertanyaan , cukup konyol untuk digunakan dalam kasus seperti const moment = require('moment'),, kecuali jika Anda adalah tipe orang yang khawatir seseorang akan mencoba melakukannya moment = dead.fish(() => pizza)nanti.
MaxWell
5
Mungkin lebih realistis untuk dikhawatirkan moment = Date.now(). Tetapi bagaimanapun juga, jika kode tersebut dianggap invarian, saya tidak melihat ada masalah dengan memberlakukannya jika memungkinkan.
James M.
3
Tidak ada yang mengatakan mereka tidak berubah, meskipun. Ini adalah kesalahpahaman umum bahwa tujuan const adalah untuk membuatnya tidak berubah, ketika itu benar-benar untuk menjamin bahwa nama tidak akan pernah merujuk objek yang berbeda dari yang diinisialisasi.
monokrom
25

Jangan khawatir tentang itu. constadalah tambahan yang luar biasa untuk JavaScript, dan saya akan merekomendasikan Anda menggunakannya semua tempat yang masuk akal. Itu membuat kode lebih kuat.

Ketika datang ke objek, constakan melindungi variabel Anda dari penugasan kembali, tetapi jika Anda membutuhkan objek abadi, Anda akan memerlukan Object.freezemetode, lihat di bawah.

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

consthanya akan melindungi dari penugasan kembali, dan freezemetode ini akan melindungi semua properti langsung. Jika Anda membutuhkan semua properti bersarang agar tidak berubah juga, maka Anda harus secara rekursif freeze.

clean_coding
sumber
14
Perhatikan itu Object.freezedangkal.
Mathias Bynens
@MathiasBynens Saya menemukan komentar ini dan saya ingin tahu apa yang Anda maksud dengan komentar itu. Bisakah Anda jelaskan?
Cole Roberts
@ColeRoberts Konsep immutability dangkal, adalah ketika referensi objek itu sendiri tidak berubah, tetapi properti masih bisa diubah. Kata kunci const hanya membuat imutabilitas yang dangkal, maka Anda perlu menggunakan Object.freeze jika semua properti juga harus tidak berubah.
clean_coding
3
@ColeRoberts Ini berarti bahwa nilai objek dalam objek yang dibekukan (yaitu objek bersarang) masih dapat dimutasi. Lihat mathiasbynens.be/notes/es6-const#immutable-values untuk informasi lebih lanjut.
Mathias Bynens
19

Dalam ES6const saya bukan tentang post immutability , saya jelaskan apa constartinya persis menurut spec.

Berdasarkan fakta-fakta obyektif itu, inilah preferensi pribadi saya:

[...] masuk akal untuk menggunakan letdan constsebagai berikut dalam kode ES6 Anda:

  • gunakan constsecara default
  • hanya digunakan letjika rebinding (yaitu segala bentuk penugasan kembali) diperlukan
  • ( vartidak boleh digunakan dalam ES6)

Meskipun subjektif, itu fakta bahwa ini paling dekat dengan maksud spec.

Orang-orang yang menggunakan letsecara default biasanya memperlakukan constvariabel sebagai konstanta (yang tidak harus, dengan desain!). Untuk masing-masing mereka sendiri, tetapi saya lebih suka menggunakan hal-hal untuk tujuan yang mereka maksudkan, dan bukan untuk beberapa makna yang dibuat-buat orang ditugaskan kepadanya berdasarkan kesalahpahaman.

Menggunakan consthanya untuk konstanta seperti menggunakan elemen HTML<aside> hanya untuk konten bilah samping.

Mathias Bynens
sumber
2
Mengapa Anda menyebutkan sesuatu constjika tidak konstan?
nu everest
3
@nueverest Karena bukan itu gunanya const. Apakah Anda membaca di atas?
Mathias Bynens
2
@MathiasBynens Saya pikir masalah (hanya?) Dengan constitu disebut const. Itu nama bodoh (dalam javascript) yang membingungkan banyak (semua?) Pengembang pada awalnya. IMO lebih baik jika consttelah dipanggil let(terutama karena letlebih pendek tetapi constjauh lebih umum) dan letdisebut sesuatu yang lain.
MrN00b
@MathiasBynens Saya mengerti tetapi mengapa menyebutnya begitu? Ini menciptakan sejumlah besar kebingungan seperti yang ditunjukkan halaman ini.
jtr13
4

Pendekatan pribadi saya, berpikir untuk membantu pembacaan dan pemahaman kode:


lethanya untuk variabel berumur pendek, didefinisikan pada satu baris dan tidak berubah setelahnya. Secara umum variabel-variabel yang ada hanya mengurangi jumlah pengetikan. Sebagai contoh:

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]
  ...
}

constuntuk semua nama yang diketahui konstan di seluruh modul. Tidak termasuk nilai konstan lokal. Dalam valuecontoh di atas, misalnya, konstan dalam cakupannya dan dapat dideklarasikan dengan const, tetapi karena ada banyak iterasi dan untuk masing-masing ada nilai dengan nama yang sama , "nilai", yang dapat menipu pembaca agar berpikir valueselalu sama. Modul dan fungsi adalah contoh terbaik dari constvariabel:

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

varuntuk segala sesuatu yang mungkin atau tidak variabel. Nama-nama yang dapat membingungkan orang-orang yang membaca kode, meskipun mereka konstan secara lokal, dan tidak cocok untuk let(yaitu, mereka tidak dilengkapi dalam deklarasi langsung sederhana) berlaku untuk dideklarasikan dengan var. Sebagai contoh:

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
}

Komentar lebih lanjut dan kemungkinan pembaruan di masa depan di sini .

fiatjaf
sumber
10
cuplikan kode kedua itu terlihat seperti pistol.
Julian
1

JavaScript agak spesial karena variabel dapat berupa fungsi dan semacamnya, tetapi pertimbangkan dalam C #, Java atau bahasa gaya C serupa lainnya:

const public void DoSomething()

The constaneh, dan itu karena deklarasi metode dalam bahasa ini tidak bisa berubah, begitu mereka dikompilasi ke dalam sesuatu yang lain, yaitu apa yang mereka lakukan, tidak peduli apa (mengabaikan beberapa hacks mengerikan yang mungkin ada).

Mengapa JavaScript harus berbeda? Jadi itu tidak dikompilasi, tetapi itu tidak berarti kita harus membuang keamanan yang dapat diberikan oleh kompiler. Menggunakan constkata kunci memberi kita lebih banyak keamanan, yang tentunya akan mengarah pada aplikasi yang lebih kuat.

Joe
sumber