Javascript beralih vs. if… else if… else


143

Kawan, saya punya beberapa pertanyaan:

  1. Apakah ada perbedaan kinerja dalam JavaScript antara switchpernyataan danif...else ?
  2. Jika demikian mengapa?
  3. Apakah perilaku switchdan if...elseperbedaan antar browser? (FireFox, IE, Chrome, Opera, Safari)

Alasan untuk mengajukan pertanyaan ini adalah sepertinya saya mendapatkan kinerja yang lebih baik pada switchpernyataan dengan sekitar 1000-an kasus di Firefox.


Diedit Sayangnya ini bukan kode saya, Javascript sedang diproduksi di sisi server dari perpustakaan yang dikompilasi dan saya tidak memiliki akses ke kode tersebut. Metode yang menghasilkan javascript disebut

CreateConditionals(string name, string arrayofvalues, string arrayofActions)

note arrayofvaluesadalah daftar yang dipisahkan koma.

apa yang ia hasilkan adalah

function [name] (value) {
  if (value == [value from array index x]) {
     [action from array index x]
  }
}

Catatan: where [name]= nama diteruskan ke fungsi serveride

Sekarang saya mengubah output dari fungsi yang akan dimasukkan ke dalam TextArea, menulis beberapa kode JavaScript untuk mem-parsing melalui fungsi, dan mengubahnya menjadi seperangkat case pernyataan.

akhirnya saya menjalankan fungsinya dan itu berjalan dengan baik tetapi kinerja berbeda di IE dan Firefox.


1
Saya akan menyarankan contoh kode untuk memeriksa apa yang optimal. Maksud saya, pasti ada alasan Anda menanyakan hal ini, bukan?
jcolebrand

Silakan posting apa yang Anda lakukan, karena ada sangat sedikit kasus dalam pengalaman panjang saya yang saya katakan pernyataan beralih 100 kasus atau 100 bagian jika seri / adalah ide yang baik.
Runcing

maaf guys bukan 100-an tapi ribuan kondisi
kawan

2
Semuanya, terima kasih atas masukannya. Tapi masalah saya sebenarnya bukan perbedaan antara statemen if dan swith. Itu adalah kode yang berjalan di dalam pernyataan itu. +1 untuk Anda semua atas bantuan Anda. Maaf atas ketidaknyamanan ini. Terkadang Anda hanya perlu membicarakannya dengan orang lain untuk menemukan solusinya.
John Hartsock

Jawaban:


113

Menjawab secara umum:

  1. Ya, biasanya
  2. Lihat Info Lebih Lanjut Di Sini
  3. Ya, karena masing-masing memiliki mesin pengolah JS yang berbeda, namun, dalam menjalankan tes di situs di bawah ini, sakelar selalu keluar melakukan if, jika tidak pada sejumlah besar iterasi.

Situs uji


1
Jika Anda menginginkan TLDR kapan menggunakan kondisional di sini adalah tautan langsung ke segmen dalam artikel yang membahas: oreilly.com/server-administration/excerpts/even-faster-websites/…
edhedges

2
@Tommy Artikel bagus, terima kasih sudah berbagi. Namun artikel tersebut menyatakan bahwa ada perbedaan kinerja yang dapat diabaikan antara switchdan if/thenpernyataan di JS. Artikel ini menyatakan ini karena switchoptimasi jerawatan dan cara fungsi mesin JS yang berbeda. Quote:Since most JavaScript engines don’t have such optimizations, performance of the switch statement is mixed.
Jasper

3
Apakah ada yang dapat diukur yang diperlihatkan dalam uraian ini? Bunyinya seperti dugaan "praktik terbaik / optimisasi dini". Itu juga ditulis 7 tahun yang lalu, jadi optimasi javascript telah sangat berubah saat ini. Dalam bahasa yang dikompilasi, perbedaan kinerja antara ketiga operasi ini "hampir tidak pernah cukup signifikan untuk diperhatikan". Jangan repot-repot mengoptimalkan hal-hal yang tidak akan memengaruhi kinerja aktual. Optimalkan keterbacaan.
Thomson Comer

3
@Tommy « Lihat Info Lebih Lanjut Di Sini » memberi 404, apa yang ada di sana?
LogicDaemon

2
@LogicDaemon - IIRC adalah tautan ke beberapa kotak teks oRielly yang masuk ke beberapa pertimbangan / diskusi kinerja JS mendalam
Tommy

61

Terkadang lebih baik tidak menggunakan keduanya. Misalnya, dalam situasi "pengiriman", Javascript memungkinkan Anda melakukan sesuatu dengan cara yang sama sekali berbeda:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Menyiapkan percabangan multi-arah dengan membuat objek memiliki banyak keuntungan. Anda dapat menambah dan menghapus fungsionalitas secara dinamis. Anda dapat membuat tabel pengiriman dari data. Anda dapat memeriksanya secara terprogram. Anda dapat membangun penangan dengan fungsi lain.

Ada overhead yang ditambahkan dari panggilan fungsi untuk mendapatkan setara dengan "case", tetapi keuntungan (ketika ada banyak kasus) dari pencarian hash untuk menemukan fungsi untuk kunci tertentu.


2
Strategi Anda bagus dan saya sering menggunakannya. Tetapi seperti yang ditunjukkan oleh @Michael Geary stackoverflow.com/a/45336805/5936119 , variabel peta harus dideklarasikan di luar konteks pengiriman jika tidak akan selalu dievaluasi kembali.
Daniel Santana

@DanielSantana benar tapi saya ragu itu cukup mahal. Secara khusus, begitu suatu fungsi awalnya diuraikan kode itu sendiri tidak perlu dibuat ulang, karena teksnya statis.
Runcing

18

Perbedaan kinerja antara a switchdan if...else if...elsekecil, pada dasarnya mereka melakukan pekerjaan yang sama. Satu perbedaan di antara mereka yang mungkin membuat perbedaan adalah bahwa ekspresi untuk diuji hanya dievaluasi sesekali switchitu dievaluasi untuk masing-masing if. Jika mengevaluasi ekspresi itu mahal, melakukannya sekali saja tentu saja lebih cepat daripada melakukannya seratus kali.

Perbedaan dalam implementasi perintah-perintah itu (dan semua skrip pada umumnya) berbeda sedikit antara browser. Adalah umum untuk melihat perbedaan kinerja yang agak besar untuk kode yang sama di browser yang berbeda.

Karena Anda hampir tidak dapat menguji kinerja semua kode di semua browser, Anda harus mencari kode yang paling cocok untuk apa yang Anda lakukan, dan mencoba untuk mengurangi jumlah pekerjaan yang dilakukan daripada mengoptimalkan cara melakukannya.


7
  1. Jika ada perbedaan, itu tidak akan pernah cukup besar untuk diperhatikan.
  2. T / A
  3. Tidak, semuanya berfungsi secara identik.

Pada dasarnya, gunakan apa pun yang membuat kode itu paling mudah dibaca. Pasti ada tempat di mana satu atau yang lain membuat konstruksi menjadi lebih bersih, lebih mudah dibaca dan lebih dapat dipelihara. Ini jauh lebih penting yang mungkin menyimpan beberapa nanodetik dalam kode JavaScript.


5
Dalam javascript khususnya, semantik dan keterbacaan (dan karenanya rawatan) mengalahkan semua perbedaan kinerja yang dilokalkan antara if..elsedan switchdisebabkan oleh versi browser yang unik, perangkat keras komputer, dan kombinasi OS.
Jball

2
Saya tidak tahu apakah saya setuju, mungkin memang diperhatikan jika digunakan dalam satu lingkaran dengan katakanlah, database besar, melintasi pohon dll.
ghoppe

2
saya pasti tidak setuju. karena aplikasi web menjadi semakin kompleks, perbedaan ini dapat menjadi signifikan untuk aplikasi dan dapat berubah tergantung pada browser.
joshvermaire

7
Yang penting adalah menulis kode yang bersih dan dapat dipelihara. Ketika masalah kinerja terlihat - profil. Kemudian tentukan kode mana yang harus diperbaiki. Jangan mengorbankan perawatan untuk masalah kinerja yang diasumsikan.
Jon Benedicto

3
'jika lain jika lain ...' adalah O (n), sedangkan 'switch' adalah O (1) atau O (log (n)). Bagaimana Anda bisa dengan jujur ​​menyatakan bahwa perbedaannya tidak akan pernah cukup besar? Miliki sejuta case dalam keadaan aktif (dengan mudah dimungkinkan jika kode tersebut dibuat) dan Anda pasti akan menyadarinya.
Dragonroot

6

Selain sintaks, sebuah saklar dapat diimplementasikan menggunakan pohon yang membuatnya O(log n), sementara jika / harus diimplementasikan dengan O(n)pendekatan prosedural. Lebih sering keduanya diproses secara prosedural dan satu-satunya perbedaan adalah sintaksis, dan terlebih lagi apakah itu benar-benar penting - kecuali jika Anda secara statis mengetikkan 10k kasus if / else?


7 tahun kemudian ... Saya tidak melihat bagaimana implementasi pohon dimungkinkan, kecuali dalam kasus nilai kasus numerik konstan).
Ed Staub

4

Jawaban Pointy menyarankan penggunaan objek literal sebagai alternatif switchatau if/ else. Saya suka pendekatan ini juga, tetapi kode dalam jawaban menciptakan mapobjek baru setiap kali dispatchfungsi dipanggil:

function dispatch(funCode) {
  var map = {
    'explode': function() {
      prepExplosive();
      if (flammable()) issueWarning();
      doExplode();
    },

    'hibernate': function() {
      if (status() == 'sleeping') return;
      // ... I can't keep making this stuff up
    },
    // ...
  };

  var thisFun = map[funCode];
  if (thisFun) thisFun();
}

Jika mapberisi banyak entri, ini dapat membuat overhead yang signifikan. Lebih baik mengatur peta tindakan hanya sekali dan kemudian menggunakan peta yang sudah dibuat setiap kali, misalnya:

var actions = {
    'explode': function() {
        prepExplosive();
        if( flammable() ) issueWarning();
        doExplode();
    },

    'hibernate': function() {
        if( status() == 'sleeping' ) return;
        // ... I can't keep making this stuff up
    },
    // ...
};

function dispatch( name ) {
    var action = actions[name];
    if( action ) action();
}

3

Apakah ada perbedaan dalm Javascript antara pernyataan sakelar dan if ... else if .... else?

Saya rasa tidak, switchberguna / singkat jika Anda ingin mencegah beberapa if-elsekondisi.

Apakah perilaku sakelar dan jika ... selain itu ... berbeda di semua browser? (FireFox, IE, Chrome, Opera, Safari)

Perilaku sama di semua browser :)


5
switch is useful/short if you want prevent multiple if-else conditions.Ya, tuan, kiriman yang bagus.
NiCk Newman

1
  1. Workbenching mungkin menghasilkan beberapa perbedaan yang sangat kecil dalam beberapa kasus tetapi cara pemrosesan tergantung pada browser sehingga tidak layak untuk diganggu
  2. Karena berbagai cara pengolahan
  3. Anda tidak dapat menyebutnya browser jika perilakunya akan berbeda

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.