jQuery: Apakah kekhususan pemilih meningkatkan kinerja dengan delegasi .on()?

Apakah ada peningkatan kinerja ketika meningkatkan kekhususan dalam pengikatan acara yang didelegasikan dengan .on()?

Bagaimana cara seseorang menguji ini?

Misalnya, apakah pernyataan kedua lebih berkinerja dibandingkan pernyataan pertama:

$('.foo').on('mouseenter', ':has(.other)', function (e) {
    console.log(e);
});

$('.bar').on('mouseenter', 'button:has(.other)', function (e) {
    console.log(e);
});

$('.foo').on('mouseenter', ':has(.other)', function (e) {
  console.log(e);
});

$('.bar').on('mouseenter', 'button:has(.other)', function (e) {
  console.log(e);
});
.foo, .bar {
  margin: 2em auto;
  text-align: center;
}
<div class="foo">
  <button type="button">Hello
    <span class="other">World</span>
  </button>
</div>

<div class="bar">
  <button type="button">Hello
    <span class="other">World</span>
  </button>
</div>

Kekhawatiran utama saya adalah bahwa mendengarkan mouseenter acara dengan delegasi akan menguras kinerja dan apakah ada cara untuk menguji kinerja pada jenis pengendali acara ini.

Perbarui

Saya harus mengklarifikasi bahwa saya tidak ingin memahami implikasi kinerja dari penggunaan delegasi secara umum. Saya berharap untuk memahami implikasi kinerja menggunakan delegasi dengan mouseenter selama interaksi pengguna (saat mouse pengguna memasukkan elemen yang didelegasikan dan tidak didelegasikan dalam elemen terikat) dan jika ada peningkatan kinerja dengan menggunakan pemilih yang lebih spesifik untuk delegasi .

Kecenderungan saya adalah berasumsi tidak ada karena setiap peristiwa harus meluap ke elemen terikat sebelum diperiksa terhadap pemilih yang didelegasikan.

Tapi apakah ada cara untuk mengujinya?


person gfullam    schedule 12.02.2015    source sumber
comment
Sudah mencoba menjalankan tes jsperf?   -  person j08691    schedule 13.02.2015
comment
Jika ada, menurut saya versi ke-2 akan memiliki performa yang kurang dapat diabaikan. Keduanya akan tetap muncul ke nenek moyangnya, dan versi kedua memerlukan pemeriksaan jenis simpul serta keberadaan kelas.   -  person JMM    schedule 13.02.2015
comment
Bagaimana saya bisa menjalankan tes jsperf pada contoh spesifik ini? Bukankah jsperf hanya menguji kinerja runtime, seperti operasi pengikatan itu sendiri, dan bukan penanganan peristiwa pada interaksi pengguna?   -  person gfullam    schedule 13.02.2015
comment
c2.com/cgi/wiki?PrematureOptimization   -  person undefined    schedule 13.02.2015
comment
TERTAWA TERBAHAK-BAHAK. Ini tidak terlalu dini. Saya sedang mengerjakan aplikasi perusahaan yang mungkin memiliki ribuan elemen DOM untuk dilintasi. Ini adalah contoh berpasangan yang pasti.   -  person gfullam    schedule 13.02.2015
comment
Saya harus mengklarifikasi bahwa saya tidak ingin memahami implikasi kinerja dari penggunaan delegasi. Saya berharap untuk memahami implikasi kinerja menggunakan delegasi dengan mouseenter dan apakah ada peningkatan kinerja dengan menggunakan pemilih yang lebih spesifik untuk delegasi. Kecenderungan saya adalah berasumsi tidak ada karena setiap peristiwa harus meluap ke elemen terikat sebelum diperiksa terhadap pemilih yang didelegasikan. Tapi apakah ada cara untuk mengujinya?   -  person gfullam    schedule 13.02.2015
comment
Saya berpendapat bahwa, secara umum, penggunaan :has dalam panggilan closest (seperti yang dilakukan on di belakang layar) akan menghasilkan kinerja yang menyedihkan. Saya akan menguji button di pemilih dan kemudian menggunakan metode .has() di panggilan balik.   -  person lonesomeday    schedule 13.02.2015
comment
@lonesomeday Itu masuk akal, tapi sayangnya saya hanya dapat mengikat langsung ke elemen container yang akan menerima tombol di lain waktu. Isi wadah ini dapat dirender ulang berapa kali pun, jadi delegasi adalah suatu keharusan.   -  person gfullam    schedule 13.02.2015
comment
@gfullam Saya yakin delegasi adalah pilihan yang tepat. Namun, saya akan berusaha keras untuk memastikan bahwa :has pemilih tidak ada di Anda string pemilih. Ini adalah pemilih jQuery, bukan browser asli, sehingga sangat lambat. Anda menggunakannya pada setiap elemen di pohon. Jika Anda melakukan pengujian lain, misalnya button, lalu gunakan .has fungsi untuk menguji elemen tersebut, elemen tersebut akan memiliki kinerja yang jauh lebih baik karena dapat menggunakan kemampuan bawaan browser dengan lebih baik.   -  person lonesomeday    schedule 13.02.2015
comment
@lonesomeday Awalnya saya telah berusaha keras untuk menghindari delegasi karena saya perlu mengikat ke induk dari pemilih kelas anak yang dikenal, sayangnya satu-satunya cara untuk melakukan ini adalah dengan :has karena Anda tidak dapat menghubungkan .has dengan penyeleksi yang didelegasikan - itu bisa hanya rantai ke elemen DOM yang ada dan pada saat pengikatan, elemen tersebut tidak ada. Karena penggunaan :has saya khawatir akan menemukan peningkatan kinerja lainnya. Penting juga bagi saya untuk memahami apa yang terjadi dan bagaimana menguji kinerja dalam situasi ini.   -  person gfullam    schedule 13.02.2015
comment
@gfullam Saya menyadarinya. Saya mengatakan bahwa Anda harus mencoba mengeluarkan :has dari pemilih dan melakukan tes di panggilan balik acara; itu akan memiliki kinerja yang jauh lebih baik. Lihat kedua contoh ini: keduanya setara secara fungsional, namun performa yang pertama jauh lebih baik.   -  person lonesomeday    schedule 13.02.2015
comment
@lonesomeday Saya suka contoh itu. Dan itu semakin dekat untuk menjawab pertanyaan saya. Bisakah Anda mempostingnya sebagai jawaban dengan penjelasan ''mengapa'' fungsi yang satu lebih berkinerja daripada yang lain? Bagaimana Anda menentukan perbedaan kinerja antara keduanya?   -  person gfullam    schedule 13.02.2015
comment
Akhirnya menemukan cara untuk merumuskan pengujian jsperf yang menunjukkan bahwa penggunaan :has di pemilih lebih sering (dalam pengujian berulang) lebih baik daripada menggunakan .has di handler; hal ini juga menunjukkan bahwa peningkatan spesifisitas, seperti pada button:has pada pemilih, secara konsisten meningkatkan kinerja. Lihat: jsperf.com/has-filter-in-delegated-event-selector   -  person gfullam    schedule 03.05.2015


Jawaban (1)


Kekhususan membantu… sedikit.

Menurut pengujian JSPerf ini, menambahkan kekhususan pada pemilih di contoh yang diposting secara konsisten meningkatkan kinerja dalam pengujian berulang, namun peningkatan tersebut dapat dianggap dapat diabaikan pada tingkat interaksi pengguna di mana peristiwa terjadi secara sporadis dalam pengulangan yang relatif kecil.

Dalam beberapa pengujian, perbedaannya cukup kecil dan berada dalam batas kesalahan sehingga dianggap setara secara statistik.

Pemfilteran pemilih di handler menyakitkan

Namun hasil yang paling mengejutkan adalah pengujian tambahan ketiga yang disarankan oleh salah satu pemberi komentar di atas yang mengeluarkan :has() dari pemilih dan menggantikannya dengan tanda .has() pada fungsi panggilan balik, yang secara konsisten bekerja lebih lambat dibandingkan menggunakan :has() pada pemilih — sering kali dengan 100 operasi per detik atau lebih.

Hal ini bisa dibilang tidak terlalu bisa diabaikan dan sangat luar biasa mengingat dokumentasi jQuery untuk :has() menunjukkan bahwa Anda harus mengharapkan kinerja yang lebih baik di sini:

Karena :has() adalah ekstensi jQuery dan bukan bagian dari spesifikasi CSS, kueri yang menggunakan :has() tidak dapat memanfaatkan peningkatan kinerja yang disediakan oleh metode DOM querySelectorAll() asli. Untuk kinerja yang lebih baik di browser modern, gunakan $( "your-pure-css-selector" ).has( selector/DOMElement ) sebagai gantinya.

Saya tidak meragukan bahwa dalam pernyataan pemilih di mana .has() hanya digunakan untuk mengurangi kumpulan elemen yang cocok, seseorang dapat mengharapkan kinerja yang lebih baik; tapi saya curiga penurunan kinerja yang ditunjukkan dalam pengujian adalah hasil dari pelanggaran konvensi itu dengan memindahkan pemeriksaan .has() ke dalam pengendali peristiwa di mana data peristiwa sedang diedarkan, objek jQuery baru sedang dibuat dari this, dan .length sedang diakses dan diperiksa dalam pernyataan if.


Formulasi tes

Untuk merumuskan pengujian, tiga tolok ukur pengikatan peristiwa dikonfigurasikan dan diterapkan ke markup HTML yang sama, kemudian kasus pengujian pemicu peristiwa yang sama — menyimulasikan pengguna mengarahkan mouse ke berbagai elemen yang didelegasikan dan tidak didelegasikan di layar — diterapkan ke masing-masing elemen. tiga tolok ukur untuk perbandingan.

Tolok ukur 1:

    $('.foo').on('mouseenter', ':has(.other)', function(e) {
      console.log(e);
    });

Tolok ukur 2:

    $('.foo').on('mouseenter', 'button:has(.other)', function(e) {
      console.log(e);
    });

Tolok ukur 3:

    $('.foo').on('mouseenter', 'button', function(e) {
      if ($(this).has('.other').length) {
        console.log(e);
      }
    });

HTML:

<div class="foo">
    <button type="button" id="A">some text</button>
    <button type="button" id="B"><span class="other">some text</span></button>
    <div id="C">some text</div>
</div>

Kasus uji:

$('#A').trigger('mouseenter');
$('#B').trigger('mouseenter');
$('#C').trigger('mouseenter');

Tangkapan layar tabel yang menunjukkan hasil pengujian JSPerf

person gfullam    schedule 04.05.2015