Rumah  >  Artikel  >  hujung hadapan web  >  tafsiran kod sumber pemilih jQuery (5): proses menghurai tokenize_jquery

tafsiran kod sumber pemilih jQuery (5): proses menghurai tokenize_jquery

WBOY
WBOYasal
2016-05-16 16:06:451253semak imbas

Analisis berikut adalah berdasarkan versi jQuery-1.10.2.js.

Yang berikut akan mengambil $("div:not(.class:contain('span')):eq(3)") sebagai contoh untuk menerangkan cara kod tokenize dan preFilter diselaraskan untuk melengkapkan penghuraian. Jika anda ingin mengetahui penjelasan terperinci bagi setiap baris kod kaedah tokenize dan kelas preFilter, sila rujuk dua artikel berikut:

http://www.jb51.net/article/63155.htm
http://www.jb51.net/article/63163.htm

Berikut ialah kod sumber kaedah tokenize, saya telah mengalih keluar semua kod yang berkaitan dengan caching, pemadanan koma dan pemadanan aksara relasi, hanya meninggalkan kod teras yang berkaitan dengan contoh semasa. Kod yang telah dialih keluar adalah sangat mudah Jika perlu, anda boleh membaca artikel di atas.

Selain itu, kod ditulis di atas teks penerangan.

Salin kod Kod adalah seperti berikut:

tokenize fungsi(pemilih, parseSahaja) {
var dipadankan, padanan, token, jenis, setakat, kumpulan, praPenapis;

soFar = pemilih;
kumpulan = [];
preFilters = Expr.preFilter;

manakala (sejauh ini) {
jika (! padan) {
groups.push(token = []);
}

dipadankan = palsu;

untuk (taip dalam Expr.filter) {
Jika ((match = matchExpr[type].exec(soFar))
&& (!preFilters[type] || (match = preFilters[type]
(perlawanan)))) {
Dipadankan = match.shift();
tokens.push({
Nilai: sepadan,
Taip : taip,
       padanan: padanan
});
SoFar = soFar.slice(matched.length);
}
}

jika (! padan) {
Rehat;
}
}

return parseOnly ? soFar.length : soFar ? tokenCache(pemilih, kumpulan).slice(0);
}

Pertama, tokenize dipanggil buat kali pertama oleh kaedah pilih semasa pelaksanaan jQuery, dan "div:not(.class:contain('span')):eq(3)" dihantar ke dalam kaedah sebagai parameter pemilih.

Salin kod Kod adalah seperti berikut:
soFar = pemilih;

soFar = "div:not(.class:contain('span')):eq(3)"

Apabila memasuki gelung while buat kali pertama, memandangkan nilai yang dipadankan belum diberikan, badan penyata berikut dalam if dilaksanakan Penyataan ini akan memulakan pembolehubah token dan menolak token ke dalam tatasusunan kumpulan.

Salin kod Kod adalah seperti berikut:
groups.push(token = []);

Selepas itu, masukkan pernyataan untuk.

Gelung pertama: ambil elemen pertama "TAG" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis dan laksanakan kod badan gelung.


Jika ((match = matchExpr[type].exec(soFar))
&& (!preFilters[type] || (match = preFilters[type]
(perlawanan)))) {


Keputusan pelaksanaan perlawanan = matchExpr[type].exec(soFar) adalah seperti berikut:

perlawanan =["div", "div"]

Pemilih pertama dalam contoh ialah div, yang sepadan dengan ungkapan biasa matchExpr["TAG"] dan preFilters["TAG"] tidak wujud, jadi badan pernyataan dalam if dilaksanakan.


dipadankan = match.shift();


Alih keluar div elemen pertama dalam padanan dan tetapkan elemen pada pembolehubah yang dipadankan Pada masa ini, matched="div", match = ["div"]

Salin kod Kod adalah seperti berikut:

tokens.push({
Nilai: sepadan,
Taip : taip,
       padanan: padanan
}

Buat objek baharu { nilai: "div", taip: "TAG", padankan: ["div"] } dan tolak objek ke dalam tatasusunan token.

Salin kod Kod adalah seperti berikut:

SoFar = soFar.slice(matched.length);

Pembolehubah soFar memadamkan div Pada masa ini, soFar=":not(.class:contain('span')):eq(3)"
Gelung kedua untuk: Ambil elemen kedua "CLASS" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis, dan laksanakan kod badan gelung.

Salin kod Kod adalah seperti berikut:

Jika ((match = matchExpr[type].exec(soFar))
&& (!preFilters[type] || (match = preFilters[type]
(perlawanan)))) {

Memandangkan soFar=":not(.class:contain('span')):eq(3)" semasa tidak sepadan dengan ungkapan biasa jenis CLASS, gelung ini tamat.
Yang ketiga untuk gelung: Ambil elemen ketiga "ATTR" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis, dan laksanakan kod badan gelung.
Begitu juga, memandangkan baki pemilih semasa bukan pemilih atribut, kitaran ini tamat.

Gelung keempat untuk: Ambil elemen keempat "CHILD" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis dan laksanakan kod badan gelung.
Begitu juga, memandangkan baki pemilih semasa bukan pemilih KANAK-KANAK, kitaran ini tamat.

Gelung kelima untuk: Ambil elemen kelima "PSEUDO" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis dan laksanakan kod badan gelung.

Salin kod Kod adalah seperti berikut:

Jika ((match = matchExpr[type].exec(soFar))
&& (!preFilters[type] || (match = preFilters[type]
(perlawanan)))) {

Keputusan pelaksanaan perlawanan = matchExpr[type].exec(soFar) adalah seperti berikut:
[":not(.class:contain('span')):eq(3)", "not", ".class:contain('span')):eq(3", undefined, undefined, undefined, undefined , undefined, undefined, undefined, undefined]

Memandangkan preFilters["PSEUDO"] wujud, kod berikut dilaksanakan:

Salin kod Kod adalah seperti berikut:

padan = praPenapis[jenis](padanan)
Kod

preFilters["PSEUDO"] adalah seperti berikut:

Salin kod Kod adalah seperti berikut:

"PSEUDO" : fungsi(padanan) {
var excess, unquoted = !match[5] && match[2];

jika (matchExpr["KANAK"].test(match[0])) {
kembalikan null;
}

jika (perlawanan[3] && padankan[4] !== tidak ditentukan) {
padan[2] = padanan[4];
} lain jika (tidak disebut
&& rpseudo.test(tidak disebut)
&& (lebihan = tokenize(tidak disebut, benar))
&& (lebihan = unquoted.indexOf(")", unquoted.length
- lebihan)
- tidak disebut.panjang)) {

padan[0] = padankan[0].slice(0, excess);
padanan[2] = unquoted.slice(0, excess);
}

kembalikan perlawanan.slice(0, 3);
}

Parameter padanan yang dihantar adalah sama dengan:

Salin kod Kod adalah seperti berikut:

[":not(.class:contain('span')):eq(3)", "not", ".class:contain('span')):eq(3", undefined, undefined, undefined, undefined , tidak ditentukan

Salin kod Kod adalah seperti berikut:

unquoted = !match[5] && match[2]

tidak dipetik = ".class:contain('span')):eq(3"

Salin kod Kod adalah seperti berikut:

if (matchExpr["KANAK"].test(match[0])) {
Kembalikan null; }

padanan[0] = ":not(.class:contain('span')):eq(3)", tidak sepadan dengan ungkapan biasa matchExpr["CHILD"] dan tidak melaksanakan penyataan nol pulangan .


Salin kod Kod adalah seperti berikut:
jika (padan[3] && padankan[4] !== tidak ditentukan) {
Padankan[2] = padankan[4]; }


Memandangkan padanan[3] dan padanan[4] kedua-duanya sama dengan tidak ditentukan, badan pernyataan else dilaksanakan.

lain jika (tidak disebut
              && rpseudo.test(tidak disebut harga)  
​​​​&& (lebihan = tokenize(tidak disebut, benar))
​​​​&& (lebihan = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)


Pada masa ini, unquoted = ".class:contain('span')):eq(3" adalah benar dan kerana unquoted contains:contain('span'), ia sepadan dengan ungkapan biasa rpseudo, jadi rpseudo. test(unquoted) adalah benar, dan kemudian panggil tokenize sekali lagi untuk menghuraikan tidak disebut lagi, seperti berikut:


lebihan = tokenize(tidak disebut, benar)


Apabila memanggil fungsi tokenize kali ini, parameter pemilih masuk adalah sama dengan ".class:contain('span')):eq(3", dan parseOnly adalah sama dengan benar. Proses pelaksanaan dalam badan fungsi ialah seperti berikut:

soFar = pemilih;


soFar = ".class:contain('span')):eq(3"
Apabila memasuki gelung while buat kali pertama, memandangkan nilai yang dipadankan belum diberikan, badan penyata berikut dalam if dilaksanakan Penyataan ini akan memulakan pembolehubah token dan menolak token ke dalam tatasusunan kumpulan.



Salin kod Kod adalah seperti berikut: groups.push(token = []);
Selepas
, masukkan pernyataan untuk.
Gelung pertama: ambil elemen pertama "TAG" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis dan laksanakan kod badan gelung.


Salin kod

Kod adalah seperti berikut: jika ((match = matchExpr[type].exec(soFar))           && (!preFilters[type] || (match = preFilters[type]
(perlawanan)))) {



Memandangkan baki pemilih semasa bukan pemilih TAG, kitaran ini tamat.
Gelung kedua untuk: Ambil elemen kedua "CLASS" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis, dan laksanakan kod badan gelung.
Keputusan pelaksanaan perlawanan = matchExpr[type].exec(soFar) adalah seperti berikut:


perlawanan = ["kelas" , "kelas"]

Memandangkan preFilters["CLASS"] tidak wujud, badan pernyataan dalam if dilaksanakan.


Salin kod

Kod adalah seperti berikut: dipadankan = match.shift();
Alih keluar kelas elemen pertama dalam padanan dan tetapkan elemen pada pembolehubah yang dipadankan Pada masa ini, matched="class", match = ["class"]

Salin kod

Kod adalah seperti berikut: tokens.push({ nilai : sepadan, Taip : taip,
padanan : padan
}

Buat objek baharu { value: "class", type: "CLASS", padankan: ["class"] } dan tolak objek ke dalam tatasusunan token.

Salin kod Kod adalah seperti berikut:

soFar = soFar.slice(matched.length);
Pembolehubah soFar memadamkan kelas Pada masa ini, soFar = ":contain('span')):eq(3"

Yang ketiga untuk gelung: Ambil elemen ketiga "ATTR" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis, dan laksanakan kod badan gelung.
Begitu juga, memandangkan baki pemilih semasa bukan pemilih atribut, kitaran ini tamat.

Gelung keempat untuk: Ambil elemen keempat "CHILD" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis dan laksanakan kod badan gelung.

Begitu juga, memandangkan baki pemilih semasa bukan pemilih KANAK-KANAK, kitaran ini tamat.

Gelung kelima untuk: Ambil elemen kelima "PSEUDO" daripada Expr.filter dan tetapkan ia kepada pembolehubah jenis dan laksanakan kod badan gelung.

Salin kod Kod adalah seperti berikut:
jika ((match = matchExpr[type].exec(soFar))
          && (!preFilters[type] || (match = preFilters[type]
(perlawanan)))) {

Keputusan pelaksanaan perlawanan = matchExpr[type].exec(soFar) adalah seperti berikut:

[":contain('span')", "contain", "'span'", "'", "span", undefined, undefined, undefined, undefined, undefined, undefined]

Memandangkan preFilters["PSEUDO"] wujud, kod berikut dilaksanakan:


Salin kod Kod adalah seperti berikut:
padan = praPenapis[jenis](padanan)

Kod preFilters["PSEUDO"] ditunjukkan di atas dan tidak akan disenaraikan di sini.

Salin kod Kod adalah seperti berikut:
"PSEUDO" : fungsi(padanan) {
var excess, unquoted = !match[5] && match[2];
Jika (matchExpr["KANAK"].test(match[0])) {
         kembali null;                                }  

Jika (padan[3] && padankan[4] !== tidak ditentukan) {
         padan [2] = padan [4]; 
} lain jika (tidak disebut
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (lebihan = tokenize(tidak disebut, benar))                                                                             && (lebihan = unquoted.indexOf(")", unquoted.length 
- berlebihan)
- tidak disebut.panjang)) {

         padanan[0] = padankan[0].slice(0, excess);          padanan[2] = unquoted.slice(0, excess); }  

Kembalikan padanan.slice(0, 3); }



Parameter padanan masuk adalah sama dengan:
[":contain('span')", "contain", "'span'", "'", "span", undefined, undefined, undefined, undefined, undefined, undefined]



Salin kod


Kod adalah seperti berikut:

unquoted = !match[5] && match[2]; tidak dipetik = "span"

Salin kod
Kod adalah seperti berikut:


if (matchExpr["KANAK"].test(match[0])) { kembalikan null; }

Oleh kerana ":contain('span')" tidak sepadan dengan ungkapan biasa matchExpr["CHILD"], badan pernyataan dalaman tidak dilaksanakan.

Salin kod Kod adalah seperti berikut:

jika (padan[3] && padankan[4] !== tidak ditentukan) {
padan[2] = padanan[4];
}

Memandangkan padanan[3] = "'" dan padanan[4] ="span", badan pernyataan if dalaman dilaksanakan dan "span" ditugaskan untuk memadankan[2]

Salin kod Kod adalah seperti berikut:

kembalikan padanan.slice(0, 3);
Mengembalikan salinan tiga elemen pertama padanan

Pada masa ini, kembali ke gelung untuk kaedah tokenize untuk meneruskan pelaksanaan Pada masa ini, nilai setiap pembolehubah adalah seperti berikut:

perlawanan = [":contain('span')", "contain", "span"]

soFar = ":contain('span')):eq(3"

Salin kod Kod adalah seperti berikut:
dipadankan = match.shift();

Alih keluar ":contain('span')" daripada tatasusunan padanan dan tetapkan ia kepada pembolehubah yang dipadankan

tokens.push({
nilai : sepadan,
Taip : taip,
padanan : padan
}


Cipta objek baharu { nilai:

":contain('span')", taip:"PSEUDO", padankan: ["contain", "span"] }, dan tolak objek ke dalam tatasusunan token.


soFar = soFar.slice(matched.length);


Pembolehubah soFar memadamkan ":contain('span')". Pada masa ini, soFar="):eq(3)", selepas itu, sehingga gelung for tamat dan gelung while dilaksanakan semula, terdapat tiada pemilih yang sah. Jadi keluar dari gelung while.


Salin kod Kod adalah seperti berikut: return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) :
tokenCache(pemilih, kumpulan).slice(0);


Memandangkan parseOnly = benar pada masa ini, panjang soFar pada masa ini dikembalikan, 6, dan kod preFilters["PSEUDO"] terus dilaksanakan

Salin kod

Kod adalah seperti berikut: lain jika (tidak disebut               && rpseudo.test(tidak disebut harga)  
​​​​&& (lebihan = tokenize(tidak disebut, benar))
​​​​&& (lebihan = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)



Berikan 6 kepada pembolehubah berlebihan, dan kemudian kod


Salin kod

Kod adalah seperti berikut: lebihan = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length

Kira: bukan kedudukan hujung pemilih (iaitu kedudukan kurungan kanan) 22


Salin kod

Kod adalah seperti berikut: padankan[0] = padankan[0].slice(0, excess); padankan[2] = unquoted.slice(0, excess);
Kira rentetan :bukan pemilih lengkap (padan[0]) dan rentetan dalam kurungannya (padan[2]) masing-masing, yang sama dengan:

padanan[0] = ":not(.class:contain('span'))"
perlawanan[2] = ".class:contain('span')"

Salin kod


Kod adalah seperti berikut: kembalikan padanan.slice(0, 3);

Mengembalikan salinan tiga elemen pertama dalam perlawanan.
Kembali ke fungsi tokenize, sekarang padankan = [":not(.class:contain('span'))", "not", ".class:contain('span')"]

Salin kod Kod adalah seperti berikut:

dipadankan = match.shift();
Alih keluar elemen pertama ":not(.class:contain('span'))" dalam padanan dan tetapkan elemen pada pembolehubah yang dipadankan Pada masa ini, matched="":not(.class:contain( '. span'))"",

padan = ["bukan", ".class:contain('span')"]

Salin kod Kod adalah seperti berikut:
tokens.push({
nilai : sepadan,
Taip : taip,
padanan : padan
}

Cipta objek baharu { nilai: ":not(.class:contain('span'))"", taip: "PSEUDO", padankan: ["not", ".class:contain('span') "] }, dan tolak objek ke dalam tatasusunan token. Pada masa ini, token mempunyai dua elemen, iaitu div dan bukan pemilih.


Salin kod Kod adalah seperti berikut:
soFar = soFar.slice(matched.length);

Pembolehubah SoFar memadamkan ":not(.class:contain('span'))". Pada masa ini, soFar=":eq(3)", selepas menamatkan gelung ini, kembali ke gelung while sekali lagi, dengan cara yang sama , untuk mendapatkan pemilih persamaan bagi elemen ketiga token, prosesnya konsisten dengan tidak, dan saya tidak akan menerangkan butiran di sini. Keputusan kumpulan akhir adalah seperti berikut: kumpulan[0][0] = {value: "div", jenis: "TAG", padanan: ["div"] }


kumpulan[0][1] = {nilai: ":not(.class:contain('span'))", taip: "PSEUDO", padanan: ["not", ".class:contain(' span')"] }

kumpulan[0][2] = {nilai: ":eq(3)", jenis: "PSEUDO", padankan: ["eq", "3"] }


return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) :
tokenCache(pemilih, kumpulan).slice(0);


Oleh kerana parseOnly = undefined, tokenCache(selector, groups).slice(0) dilaksanakan Pernyataan ini menolak kumpulan ke dalam cache dan mengembalikan salinannya.
Daripada ini, semua penghuraian selesai Sesetengah orang mungkin bertanya, elemen kedua di sini tidak dihuraikan Ya, ini perlu dihuraikan semula dalam operasi sebenar. Sudah tentu, jika anda boleh menyimpan hasil pemilih yang sah dalam cache apabila anda baru sahaja menghuraikan "class:contain('span')):eq(3", anda boleh mengelak menghuraikan sekali lagi dan meningkatkan kelajuan pelaksanaan. Tetapi ini Ia hanya meningkatkan kelajuan larian semasa kerana semasa pelaksanaan, apabila ".class:contain('span')" diserahkan untuk analisis sekali lagi, ia akan disimpan dalam cache. Pada ketika ini, keseluruhan proses pelaksanaan telah berakhir.


Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn