浅谈 jQuery 核心架构设计
jQuery对于大家而言并不陌生,因此关于它是什么以及它的作用,在这里我就不多言了,而本篇文章的目的是想通过对源码简单的分析来讨论 jQuery 的核心架构设计,以及jQuery 是如何利用javascript中的高级特性来构建如此伟大的javascript库。
1 初识jQuery
从核心功能来看,jQuery仅仅做了一件简单而又平凡的事:查询。它的语法如此简洁明了,以致于很多人在不知道javascript是什么的时候就已经会用jQuery了,用一个词形容就是:大道至简。 从设计层面来看,我们可以将jQuery提供方法分为两大类:静态方法和实例方法。静态方法就是直接通过$访问的方法,这些方法一般不对dom元素操作,而是提供了一些常用的工具,比如ajax请求、以及对字符串的一些常用操作,除此之外,jQuery还提供了对自身的扩展机制,你可以通过extend方法来编写你需要的组件。而实例方法和静态方法不一样,它是用来对jQuery查询的DOM元素进行操作,jQuery执行$()会构建一个jQuery对象,这个对象以数组的方法存储查询出的所有DOM元素,然后在这个对象的原型链上实现了对这些DOM操作的方法,比如each()方法就是用来遍历每一个DOM元素的。你可能会注意到,我刚说这个对象“以数组的方式”存储,那就是说,jQuery构建的这个对象不是数组,那这个对象到底是什么? 其实这个对象就是jQuery的核心,也被称作“jQuery对象”。因此,本文的重点就是对jQuery对象进行分析和讨论。
2 jQuery对象
一般情况下,我们会这样使用jQuery:
$('div').each(function(index){ //this ...});
$('div')执行完后回返回一个jQuery对象,each()方法是对这个对象中的DOM元素进行遍历,我们先看看$('div')的执行过程(本文源码摘自jQuery 3.0):
jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); }
这个方法就是$('div')的入口方法,$是jQuery的简写,就相当于jQuery('div') ,可以看出,这个方法只做了一件事,那就是返回jQuery.fn.init()函数的实例对象,那jQuery.fn.init 又是什么呢,我们再看下面的代码:
init = jQuery.fn.init = = jQuery.fn;
jQuery.fn.init和init引用了同一个方法,这个方法根据selector查询出符合条件的DOM元素,并返回,可你会发现,返回的是this,这个this是什么呢?我们待会分析,先看下面的这句话:
init.prototype = jQuery.fn;
这句话是什么意思呢,这句话是让init方法的prototype对象指向了jQuery.fn对象,那jQuery.fn又是什么鬼? 我们继续看代码:
jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, // Execute a callback for every element in the matched set. each: function( callback ) { return jQuery.each( this, callback ); }, splice: arr.splice };
为了节省篇幅,我省略了其中一些代码,从这里可以看出,jQuery.fn 其实就是jQuery的原型对象,这个原型对象中定义了一些对this对象进行操作的方法。到这里,你是不是感觉到有点绕,不要着急,我们来梳理一下思路:jQuery首先定义了一个init方法,然后在init的原型对象prototype上定义了一系列操作方法。最后将init方法的实例对象返回。所以上面的过程可以简化如下(伪代码表示):
var init = function(selector,context,root){ //... return this; } init.prototype = { length:0, each:function(callback){ //... }, splice:[].splice } jQuery = function(selector,context,root){ return new init(selector,context,root); }
那么问题来了,jQuery.fn中的方法为什么不直接定义在init的prototype上,而要定义在jQuery的原型对象上?
其实,这样做的目的是为了提高jQuery的查询效率,如果直接定义在init的prototype对象上,那么每执行一次查询,就会在内存中创建这样一个庞大的prototype对象,而如果把这个对象定义在jQuery的prototype上,在jQuery加载时,这个对象就会被初始化并一直存在于内存中,以后每次执行$()时,只需要将init中的prototype指向这个对象就可以了,而不用每次都去创建一遍相同的对象。
我们再来看看 init 函数中返回的 this 到底是什么,我在之前的博客中讲过,函数中的this总是指向运行期的调用者,那init的调用者是谁呢?在上面代码中似乎找不到调用者,这时我们就需要深入的理解new运算符的运行机制了,借用我之前在博客中对new运算符的描述,我们对new init()的执行过程进行如下分解:
new init(selector,context,root) = { var obj = {}; obj.__proto__ = init.prototype; init.call(obj,selector,context,root); return typeof result === 'obj'? result : obj; }
从上述分解过程可以看出,javascript在通过 new 来创建一个实例对象的时候,会先创建了一个普通对象obj,然后将obj的内部属性__proto__指向了init的原型对象,因此obj的原型链将被改变,而第3步使用call方法调用init(),所以init中的this指的就是这里的obj对象。
init()执行以后,会将匹配到的所有DOM对象以数组的方式存储到this对象中并返回,也就是返回了obj对象,而new运算符最终也会将这个 obj 对象返回以作为新的实例对象。所以new运算符返回的这个实例对象具备两个特点:一是包含了DOM查询结果集,二是其原型链继承了init的prototype,而 init 的 prototype 又指向了jQuery.fn对象,因此实例对象也具备了这些操作方法。
jQuery每执行一次查询就会创建一个jQuery对象,而在同一个应用程序中,所有jQuery对象都会共享同一个jQuery原型对象。因此,jQuery对象不仅包含了DOM查询结果集,还继承了jQuery原型对象上的操作方法。这样,你就可以在查询后直接调用方法来操作这些DOM元素了。这就是jQuery的核心架构设计,简单、方便、实用!
如果你还不理解上面的讲解,不要着急,我按照jQuery的设计思路写了一个完整的小项目jDate,你可以对比着理解!jDate项目已上传至GitHub,你可以点击这里查看完整代码:jDate ,如有不同见解,欢迎讨论!
3 jQuery 的缺陷
通过对jQuery的核心架构分析,我们会发现,每执行一次查询,jQuery就要在内存中构建一个复杂的jQuery对象,虽然说每个jQuery对象都共享同一个jQuery原型,但jQuery的查询过程远比你想象的要复杂,它既要考虑各种不同的匹配标识,同时又要考虑不同浏览器的兼容性。因此,如果你只是对DOM做一些简单的操作,建议使用原生方法 querySelector 替代 jQuery,不过在使用原生方法时,对于不同的应用场景你可能要做一些兼容性的工作,你要学会取舍,不要过度依赖jQuery!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



GolangRabbitMQ: Reka bentuk seni bina dan pelaksanaan sistem baris gilir mesej yang sangat tersedia memerlukan contoh kod khusus Pengenalan: Dengan pembangunan berterusan teknologi Internet dan aplikasinya yang meluas, baris gilir mesej telah menjadi bahagian yang amat diperlukan dalam sistem perisian moden. Sebagai alat untuk melaksanakan penyahgandingan, komunikasi tak segerak, pemprosesan toleransi kesalahan dan fungsi lain, baris gilir mesej menyediakan ketersediaan tinggi dan sokongan berskala untuk sistem teragih. Sebagai bahasa pengaturcaraan yang cekap dan ringkas, Golang digunakan secara meluas untuk membina sistem keselarasan tinggi dan berprestasi tinggi.

Dengan perkembangan pesat Internet Perkara dan pengkomputeran awan, pengkomputeran tepi secara beransur-ansur menjadi kawasan panas baharu. Pengkomputeran tepi merujuk kepada pemindahan pemprosesan data dan keupayaan pengkomputeran daripada pusat pengkomputeran awan tradisional ke nod tepi peranti fizikal untuk meningkatkan kecekapan pemprosesan data dan mengurangkan kependaman. Sebagai pangkalan data NoSQL yang berkuasa, MongoDB menerima lebih banyak perhatian untuk aplikasinya dalam bidang pengkomputeran tepi. 1. Amalan menggabungkan MongoDB dengan pengkomputeran tepi Dalam pengkomputeran tepi, peranti biasanya mempunyai sumber pengkomputeran dan storan yang terhad. Dan MongoDB

Dengan perkembangan pesat Internet, pembangunan perisian telah menjadi lebih dan lebih kompleks. Untuk menghadapi cabaran ini, seni bina perisian terus berkembang, daripada aplikasi tunggal awal kepada seni bina perkhidmatan mikro. Dengan populariti seni bina perkhidmatan mikro, semakin ramai pembangun mula menggunakan gRPC sebagai protokol komunikasi antara perkhidmatan mikro. go-zero ialah rangka kerja perkhidmatan mikro berdasarkan gRPC. Artikel ini akan memperkenalkan corak reka bentuk seni bina go-zero dan amalan terbaik. 1. seni bina rangka kerja go-zero Rajah 1: seni bina rangka kerja go-zero Rajah 1

Sebagai bahasa pengaturcaraan berprestasi tinggi, bahasa Go sangat popular dalam pembinaan sistem teragih. Kelajuan tinggi dan kependaman yang sangat rendah memudahkan pembangun melaksanakan seni bina teragih berskala tinggi. Terdapat banyak isu seni bina yang perlu dipertimbangkan sebelum membina sistem teragih. Cara mereka bentuk seni bina yang lebih mudah diselenggara, berskala dan stabil adalah isu penting yang dihadapi oleh semua pembangun sistem teragih. Menggunakan bahasa Go untuk membina sistem teragih boleh menjadikan pilihan seni bina ini lebih mudah dan jelas. Coroutine yang cekap Bahasa Go secara asli menyokong coroutine.

Projek PHP berskala besar boleh mengguna pakai reka bentuk seni bina berasaskan rangka kerja, seperti seni bina berlapis atau seni bina MVC, untuk mencapai kebolehskalaan, kebolehselenggaraan dan kebolehujian. Seni bina berlapis termasuk lapisan pandangan, lapisan logik perniagaan dan lapisan akses data seni bina MVC membahagikan aplikasi kepada model, pandangan dan pengawal. Seni bina rangka kerja pelaksanaan menyediakan reka bentuk modular yang memudahkan untuk menambah ciri baharu, mengurangkan kos penyelenggaraan dan menyokong ujian unit.

Reka bentuk seni bina dan pelaksanaan kod PHP modul pengurusan SKU pusat membeli-belah 1. Pengenalan Dengan perkembangan pesat e-dagang, skala dan kerumitan pusat membeli-belah juga semakin meningkat. Modul pengurusan SKU (StockKeepingUnit) pusat membeli-belah ialah salah satu modul teras pusat membeli-belah dan bertanggungjawab untuk menguruskan inventori, harga, atribut dan maklumat lain produk. Artikel ini akan memperkenalkan reka bentuk seni bina dan pelaksanaan kod PHP modul pengurusan SKU pusat membeli-belah. 2. Reka bentuk seni bina Reka bentuk pangkalan data Reka bentuk pangkalan data modul pengurusan SKU adalah asas kepada keseluruhan seni bina. SKU pusat beli-belah

Cara mereka bentuk seni bina perkhidmatan mikro PHP berprestasi tinggi Dengan perkembangan pesat Internet, seni bina perkhidmatan mikro telah menjadi pilihan pertama bagi banyak perusahaan untuk membina aplikasi berprestasi tinggi. Sebagai gaya seni bina modular yang ringan, perkhidmatan mikro boleh membahagikan aplikasi kompleks kepada unit perkhidmatan yang lebih kecil dan bebas, memberikan kebolehskalaan, kebolehpercayaan dan kebolehselenggaraan yang lebih baik melalui kerjasama bersama. Artikel ini akan memperkenalkan cara mereka bentuk seni bina perkhidmatan mikro PHP berprestasi tinggi dan menyediakan contoh kod khusus. 1. Pisahkan perkhidmatan mikro Sebelum mereka bentuk seni bina perkhidmatan mikro PHP berprestasi tinggi,

Panduan Reka Bentuk Senibina Keselamatan Laman Web: Pelaksanaan PHP Firewall Pengenalan: Dalam era Internet hari ini, masalah keselamatan laman web menjadi semakin serius Penggodam sentiasa menggunakan kelemahan untuk menceroboh laman web, mencuri maklumat pengguna atau mengganggu operasi biasa laman web. Untuk melindungi privasi dan keselamatan tapak web dan penggunanya, adalah penting untuk mewujudkan seni bina keselamatan yang boleh dipercayai. Artikel ini akan menumpukan pada pelaksanaan tembok api PHP dan menyediakan panduan untuk seni bina keselamatan tapak web. 1. Apakah tembok api PHP? Firewall PHP ialah langkah keselamatan yang menyekat serangan berniat jahat dan pencerobohan dengan menapis
