Kapan operator koma berguna?

88

Saya membaca ini pertanyaan tentang "koma operator" dalam ekspresi ( ,) dan docs MDN tentang hal itu, tapi aku tidak bisa memikirkan sebuah skenario di mana hal ini berguna.

Jadi, kapan operator koma berguna?

gdoron mendukung Monica
sumber
2
var i, j, k;vs var i; var j, var k?
Salman A
15
@Tokopedia Saya tidak yakin ini ada hubungannya dengan ,operator. Baris itu juga valid C#, tetapi ,operatornya tidak ada di sana.
gdoron mendukung Monica
2
@Tokopedia Aku melakukannya. Tidak menemukannya, beri tahu saya ...
gdoron mendukung Monica
5
@SalmanA a ,tidak selalu ,operator (dan tidak pernah menjadi ,operator di C #). Jadi C # bisa kekurangan ,operator sementara masih bebas menggunakan ,sebagai bagian dari sintaks.
Seth Carnegie
8
Saya pikir jawaban di sini telah menyimpulkan fakta bahwa ,tidak banyak digunakan (dan tidak setiap kemunculan a ,adalah operator koma) . Tetapi Anda dapat meminjamnya dan Array untuk melakukan pertukaran variabel secara inline tanpa membuat variabel sementara. Mengingat Anda ingin menukar nilai adan b, Anda bisa melakukannya a = [b][b = a,0]. Ini menempatkan arus bdi Array. Yang kedua []adalah notasi akses properti. Indeks yang diakses adalah 0, tetapi tidak sebelum ditetapkan ake b, yang sekarang aman karena bdisimpan di Array. yang ,memungkinkan kita melakukan beberapa ekspresi di [].

Jawaban:

128

Berikut ini mungkin tidak terlalu berguna karena Anda tidak menulisnya sendiri, tetapi minifier dapat menyusutkan kode menggunakan operator koma. Sebagai contoh:

if(x){foo();return bar()}else{return 1}

akan menjadi:

return x?(foo(),bar()):1

The ? :operator dapat digunakan sekarang, karena operator koma (sampai batas tertentu) memungkinkan untuk dua pernyataan yang akan ditulis sebagai satu pernyataan.

Ini adalah berguna dalam yang memungkinkan untuk beberapa kompresi rapi (39 -> 24 byte di sini).


Saya ingin menekankan fakta bahwa koma di var a, badalah tidak operator koma karena tidak ada dalam suatu ekspresi . Koma memiliki arti khusus dalam var pernyataan . a, bdalam sebuah ekspresi akan mengacu pada dua variabel dan mengevaluasi b, yang bukan kasusnya var a, b.

pimvdb.dll
sumber
3
Bagaimana pendapat Anda tentang itu? Apakah Anda membacanya di suatu tempat? Apakah itu benar-benar digunakan?
gdoron mendukung Monica
16
Saya baru saja mengotak-atik Closure Compiler beberapa hari yang lalu untuk melihat apa yang sebenarnya dilakukannya, dan saya memperhatikan substitusi ini.
pimvdb
2
Penggunaan serupa yang menurut saya berguna dalam kode Anda adalah untuk menetapkan beberapa variabel dalam pernyataan if inline. Misalnya: if (condition) var1 = val1, var2 = val2;Saya pribadi berpikir menghindari tanda kurung jika memungkinkan membuat kode lebih mudah dibaca.
Aidiakapi
2
Tentang satu-satunya saat saya menggunakan operator koma adalah ketika saya menambahkan pernyataan log ke ekspresi (foo => (console.log ('foo', foo), foo)), atau jika saya terlalu pintar dengan pengurangan iterasi . (pairs.reduce ((acc, [k, v]) => (acc [k] = v, acc), {}))
Joseph Sikorski
38

Operator koma memungkinkan Anda meletakkan beberapa ekspresi di tempat yang diharapkan satu ekspresi. Nilai yang dihasilkan dari beberapa ekspresi yang dipisahkan dengan koma akan menjadi nilai ekspresi yang dipisahkan koma terakhir.

Saya pribadi tidak terlalu sering menggunakannya karena tidak banyak situasi di mana lebih dari satu ekspresi diharapkan dan tidak ada cara yang kurang membingungkan untuk menulis kode daripada menggunakan operator koma. Satu kemungkinan menarik adalah di akhir forpengulangan ketika Anda ingin lebih dari satu variabel bertambah:

// j is initialized to some other value
// as the for loop executes both i and j are incremented
// because the comma operator allows two statements to be put in place of one
for (var i = 0; i < items.len; i++, j++) {
    // loop code here that operates on items[i] 
    // and sometimes uses j to access a different array
}

Di sini Anda melihat bahwa i++, j++dapat diletakkan di tempat di mana satu ekspresi diperbolehkan. Dalam kasus khusus ini, beberapa ekspresi digunakan untuk efek samping sehingga tidak masalah bahwa ekspresi gabungan mengambil nilai yang terakhir, tetapi ada kasus lain di mana hal itu mungkin benar-benar penting.

jfriend00
sumber
38

Operator Koma sering kali berguna saat menulis kode fungsional dalam Javascript.

Pertimbangkan kode ini yang saya tulis untuk SPA beberapa waktu lalu yang memiliki sesuatu seperti berikut

const actions = _.chain(options)
                 .pairs() // 1
                 .filter(selectActions) // 2
                 .map(createActionPromise) // 3
                 .reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
                 .value();

Ini adalah skenario yang cukup kompleks, tetapi dunia nyata. Bersabarlah sementara saya menjelaskan apa yang terjadi, dan dalam prosesnya buat kasus untuk Operator Koma.


Ini menggunakan rangkaian Underscore ke

  1. Bongkar semua opsi yang diteruskan ke fungsi ini menggunakan pairs yang akan berubah { a: 1, b: 2}menjadi[['a', 1], ['b', 2]]

  2. Larik pasangan properti ini difilter oleh pasangan mana yang dianggap sebagai 'tindakan' dalam sistem.

  3. Kemudian indeks kedua dalam larik diganti dengan fungsi yang mengembalikan janji yang mewakili tindakan itu (menggunakan map)

  4. Akhirnya panggilan ke reduceakan menggabungkan setiap "array properti" ( ['a', 1]) kembali menjadi objek akhir.

Hasil akhirnya adalah versi optionsargumen yang diubah , yang hanya berisi kunci yang sesuai dan nilainya dapat dikonsumsi oleh fungsi pemanggil.


Lihat saja

.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})

Anda dapat melihat fungsi pengurangan dimulai dengan objek status kosong state, dan untuk setiap pasangan yang mewakili kunci dan nilai, fungsi mengembalikan stateobjek yang sama setelah menambahkan properti ke objek yang sesuai dengan pasangan kunci / nilai. Karena sintaks fungsi panah ECMAScript 2015, badan fungsi adalah ekspresi, dan sebagai hasilnya, Operator Koma memungkinkan fungsi "iterasi" yang ringkas dan berguna .

Secara pribadi saya telah menemukan banyak kasus saat menulis Javascript dengan gaya yang lebih fungsional dengan ECMAScript 2015 + Fungsi Panah. Karena itu, sebelum menemukan fungsi panah (seperti pada saat penulisan pertanyaan), saya tidak pernah menggunakan operator koma dengan cara yang disengaja.

Syynth
sumber
2
Ini adalah satu-satunya jawaban yang sangat berguna sehubungan dengan bagaimana / kapan seorang programmer dapat menggunakan operator koma. Sangat berguna terutama direduce
hgoebl
Nice jawaban, tetapi jika saya bisa menyarankan sesuatu yang sedikit lebih mudah dibaca: .reduce((state, [key, value]) => (state[key] = value, state), {}). Dan saya menyadari ini mengalahkan tujuan jawaban tetapi .reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})akan menghilangkan kebutuhan akan operator koma sepenuhnya.
Patrick Roberts
Sementara Object.assign mungkin lebih idiomatis akhir-akhir ini, atau bahkan hanya operator penyebaran, saya tidak yakin mereka sedang digunakan secara luas pada saat itu. Saya juga akan menunjukkan bahwa meskipun operator koma sedikit lebih tidak jelas, ini dapat menghasilkan lebih sedikit sampah dalam situasi di mana kumpulan data sangat besar. Penghancuran itu pasti akan membantu keterbacaan!
Syynth
18

Penggunaan lain dari operator koma adalah untuk menyembunyikan hasil yang tidak Anda pedulikan di repl atau konsol, semata-mata untuk kenyamanan.

Misalnya, jika Anda mengevaluasi myVariable = aWholeLotOfTextdi repl atau konsol, ini akan mencetak semua data yang baru saja Anda tetapkan. Ini mungkin halaman dan halaman, dan jika Anda memilih untuk tidak melihatnya, Anda dapat mengevaluasi myVariable = aWholeLotOfText, 'done', dan repl / console akan mencetak 'selesai'.

Oriel dengan benar menunjukkan bahwa kustomisasi toString()atau get()fungsi bahkan dapat membuat ini berguna.

Julian de Bhal
sumber
1
Ha, ide yang sangat bagus! (Akhirnya jawaban yang benar-benar menjawab pertanyaan tidak seperti hampir semua jawaban {dan 3 jawaban dihapus yang Anda perlukan reputasi 20K untuk melihatnya ...})
gdoron mendukung Monica
1
Jika nilai yang ditetapkan adalah sebuah objek, konsol mungkin mencoba untuk menampilkannya dengan baik. Untuk melakukan itu mungkin misalnya memanggil getter, yang bisa mengubah status objek. Menggunakan koma dapat mencegah hal ini.
Oriol
@Oriol - Bagus! Anda sepenuhnya benar. Entah bagaimana ini menjadi berpotensi berguna terasa sedikit mengecewakan :)
Julian de Bhal
13

Operator koma tidak khusus untuk JavaScript, ini tersedia dalam bahasa lain seperti C dan C ++ . Sebagai operator biner, ini berguna ketika operan pertama, yang umumnya merupakan ekspresi, memiliki efek samping yang diinginkan yang dibutuhkan oleh operan kedua. Salah satu contoh dari wikipedia:

i = a += 2, a + b;

Jelas Anda dapat menulis dua baris kode yang berbeda, tetapi menggunakan koma adalah pilihan lain dan terkadang lebih mudah dibaca.

taskinoor.dll
sumber
1
Pikirkan ini sebagai alternatif, meskipun definisi kebaikan mungkin berbeda dari orang ke orang. Namun, saya tidak dapat menemukan contoh di mana Anda HARUS menggunakan koma. Hal serupa lainnya adalah terner?: Operator. Itu selalu bisa diganti dengan if-else tapi terkadang?: Membuat kode lebih mudah dibaca daripada if-else. Konsep yang sama juga berlaku untuk koma.
taskinoor
BTW, saya tidak mempertimbangkan penggunaan koma dalam deklarasi variabel atau menginisialisasi beberapa variabel dalam lingkaran. Dalam kasus tersebut, koma lebih baik.
taskinoor
2
ini terlihat membingungkan af ... wtf.
Timmerz
6

Saya tidak setuju dengan Flanagan, dan mengatakan, koma itu sangat berguna dan memungkinkan untuk menulis kode yang lebih mudah dibaca dan elegan, terutama ketika Anda tahu apa yang Anda lakukan:

Berikut artikel yang sangat mendetail tentang penggunaan koma:

Beberapa contoh dari luar sana untuk bukti demonstrasi:

function renderCurve() {
  for(var a = 1, b = 10; a*b; a++, b--) {
    console.log(new Array(a*b).join('*'));
  }
}

Generator fibonacci:

for (
    var i=2, r=[0,1];
    i<15;
    r.push(r[i-1] + r[i-2]), i++
); 
// 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377

Temukan elemen induk pertama, analog dari .parent()fungsi jQuery :

function firstAncestor(el, tagName) {
    while(el = el.parentNode, el && (el.tagName != tagName.toUpperCase()));
    return el;
}

//element in http://ecma262-5.com/ELS5_HTML.htm
var a = $('Section_15.1.1.2'); 

firstAncestor(a, 'div'); //<div class="page">
shaman.sir
sumber
7
Saya tidak yakin apakah saya akan mengatakan bahwa semua itu lebih mudah dibaca tetapi tentu saja cukup keren jadi +1
Chris Marisic
1
Anda tidak memerlukan koma di while loop pada contoh terakhir, while ((el = el.parentNode) && (el.tagName != tagName.toUpperCase()))akan baik-baik saja dalam konteks itu.
PitaJ
5

Saya belum menemukan penggunaan praktisnya selain itu tetapi di sini adalah satu skenario di mana James Padolsey dengan baik menggunakan teknik ini untuk deteksi IE dalam loop sementara:

var ie = (function(){

    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while ( // <-- notice no while body here
        div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
        all[0]
    );

    return v > 4 ? v : undef;

}());

Kedua baris ini harus dijalankan:

div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]

Dan di dalam operator koma, keduanya dievaluasi meskipun seseorang dapat membuatnya menjadi pernyataan terpisah.

Sarfraz
sumber
3
Ini bisa jadi sebuah do- whileloop.
Casey Chu
5

Ada sesuatu yang "aneh" yang bisa dilakukan dalam JavaScript memanggil suatu fungsi secara tidak langsung dengan menggunakan operator koma.

Ada penjelasan panjang di sini: Pemanggilan fungsi tidak langsung dalam JavaScript

Dengan menggunakan sintaks ini:

(function() {
    "use strict";
  
    var global = (function () { return this || (1,eval)("this"); })();
    console.log('Global === window should be true: ', global === window);
  
    var not_global = (function () { return this })();
    console.log('not_global === window should be false: ', not_global === window);
  
  }());

Anda bisa mendapatkan akses ke variabel global karena evalberfungsi secara berbeda saat dipanggil secara langsung vs tidak langsung.

Jeremy J Starcher
sumber
4

Saya telah menemukan operator koma paling berguna saat menulis pembantu seperti ini.

const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);

Kamu bisa mengganti koma dengan || atau &&, tetapi Anda harus mengetahui apa yang dikembalikan fungsi tersebut.

Lebih penting dari itu, pemisah koma mengkomunikasikan maksud - kode tidak peduli apa yang mengevaluasi operan kiri, sedangkan alternatif mungkin memiliki alasan lain untuk berada di sana. Ini pada gilirannya membuatnya lebih mudah untuk dipahami dan difaktor ulang. Jika tipe kembalian fungsi pernah berubah, kode di atas tidak akan terpengaruh.

Secara alami Anda dapat mencapai hal yang sama dengan cara lain, tetapi tidak sesingkat itu. Jika || dan && menemukan tempat yang umum digunakan, begitu juga operator koma.

Lambros Symeonakis
sumber
Mirip dengan apa yang dilakukan Ramda \ Lodash dengan tap( ramdajs.com/docs/#tap ). Pada dasarnya, Anda sedang menjalankan efek samping dan kemudian mengembalikan nilai awal; sangat berguna dalam pemrograman fungsional :)
avalanche1
1

Satu kasus khas yang akhirnya saya gunakan adalah selama penguraian argumen opsional. Saya pikir itu membuatnya lebih mudah dibaca dan lebih ringkas sehingga parsing argumen tidak mendominasi badan fungsi.

/**
 * @param {string} [str]
 * @param {object} [obj]
 * @param {Date} [date]
 */
function f(str, obj, date) {
  // handle optional arguments
  if (typeof str !== "string") date = obj, obj = str, str = "default";
  if (obj instanceof Date) date = obj, obj = {};
  if (!(date instanceof Date)) date = new Date();

  // ...
}
Rich Remer
sumber
Meskipun saya sendiri tidak menyukainya, ini adalah satu-satunya contoh yang diberikan siapa pun yang menurut saya dapat dikatakan seseorang lebih baik untuk dibaca daripada daftar ekuivalen pernyataan individu yang setara tanpa saya berpikir bahwa pernyataan itu benar-benar gila.
Titik koma
1

Katakanlah Anda memiliki array:

arr = [];

Saat Anda pushmasuk ke dalam array itu, Anda jarang tertarik dengan pushnilai yang dikembalikan, yaitu panjang baru dari array tersebut, melainkan array itu sendiri:

arr.push('foo')  // ['foo'] seems more interesting than 1

Dengan menggunakan operator koma, kita dapat mendorong ke array, menentukan array sebagai operan terakhir untuk koma, dan kemudian menggunakan hasilnya - array itu sendiri - untuk panggilan metode array berikutnya, semacam rangkaian:

(arr.push('bar'), arr.push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
Dexygen
sumber
-2

Area lain di mana operator koma dapat digunakan adalah Kode Obfuscation .

Katakanlah seorang pengembang menulis beberapa kode seperti ini:

var foo = 'bar';

Sekarang, dia memutuskan untuk mengaburkan kode tersebut. Alat yang digunakan dapat mengubah kode seperti ini:

var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'

Demo: http://jsfiddle.net/uvDuE/

Stephan
sumber
1
@gdoron Silakan lihat jawaban ini stackoverflow.com/a/17903036/363573 tentang Operator Koma di C ++. Anda akan melihat komentar James Kanze tentang kebingungan.
Stephan