jQuery技术内幕:深入解析jQuery架构设计与实现原理. 2.2 总体结构

简介:

2.2 总体结构

构造jQuery对象模块的总体源码结构如代码清单2-1所示。

代码清单2-1 构造 jQuery 对象模块的总体源码结构

 16 (function( window, undefined ) {

        // 构造 jQuery 对象

 22    var jQuery = (function() {

 25       var jQuery = function( selector, context ) {

 27              return new jQuery.fn.init( selector, context, rootjQuery );

 28          },

              // 一堆局部变量声明

 97       jQuery.fn = jQuery.prototype = {

 98          constructor: jQuery,

 99          init: function( selector, context, rootjQuery ) { ... },

              // 一堆原型属性和方法

319       };

322       jQuery.fn.init.prototype = jQuery.fn;

324       jQuery.extend = jQuery.fn.extend = function() { ... };

388       jQuery.extend({

              // 一堆静态属性和方法

892       });

955       return jQuery;

 957    })();

         // 省略其他模块的代码

9246     window.jQuery = window.$ = jQuery;

9266 })( window );

下面简要梳理下这段源码。

第16~9266行是最外层的自调用匿名函数,第1章中介绍过,当jQuery初始化时,这个自调用匿名函数包含的所有JavaScript代码将被执行。

第22行定义了一个变量jQuery,第22~957行的自调用匿名函数返回jQuery构造函数并赋值给变量jQuery,最后在第9246行把这个jQuery变量暴露给全局作用域window,并定义了别名$。

在第22~957行的自调用匿名函数内,第25行又定义了一个变量jQuery,它的值是jQuery构造函数,在第955行返回并赋值给第22行的变量jQuery。因此,这两个jQuery变量是等价的,都指向jQuery构造函数,为了方便描述,在后文中统一称为构造函数jQuery()。

第97~319行覆盖了构造函数jQuery()的原型对象。第98行覆盖了原型对象的属性constructor,使它指向jQuery构造函数;第99行定义了原型方法jQuery.fn.init(),它负责解析参数selector和context的类型并执行相应的查找;在第27行可以看到,当我们调用jQuery构造函数时,实际返回的是jQuery.fn.init()的实例;此外,还定义了一堆其他的原型属性和方法,例如,selector、length、size()、toArray()等。

第322行用jQuery构造函数的原型对象jQuery.fn覆盖了jQuery.fn.init()的原型对象。

第324行定义了jQuery.extend()和jQuery.fn.extend(),用于合并两个或多个对象的属性到第一个对象;第388~892行执行jQuery.extend()在jQuery构造函数上定义了一堆静态属性和方法,例如,noConflict()、isReady、readyWait、holdReady()等。

看上去代码清单2-1所述的总体源码结构有些复杂,下面把疑问和难点一一罗列,逐个分析。

1)为什么要在构造函数jQuery()内部用运算符new创建并返回另一个构造函数的实例?

通常我们创建一个对象或实例的方式是在运算符new后紧跟一个构造函数,例如,newDate()会返回一个Date对象;但是,如果构造函数有返回值,运算符new所创建的对象会被丢弃,返回值将作为new表达式的值。

jQuery利用了这一特性,通过在构造函数jQuery()内部用运算符new创建并返回另一个构造函数的实例,省去了构造函数jQuery()前面的运算符new,即我们创建jQuery对象时,可以省略运算符new直接写jQuery()。

为了拼写更方便,在第9246行还为构造函数jQuery()定义了别名$,因此,创建jQuery对象的常见写法是$()。

2)为什么在第97行执行jQuery.fn = jQuery.prototype,设置jQuery.fn指向构造函数jQuery()的原型对象jQuery.prototype?

jQuery.fn是jQuery.prototype的简写,可以少写7个字符,以方便拼写。

3)既然调用构造函数jQuery()返回的jQuery对象实际上是构造函数jQuery.fn.init()的实例,为什么能在构造函数jQuery.fn.init()的实例上调用构造函数jQuery()的原型方法和属性?例如,$('#id').length和$('#id').size()。

在第322行执行jQuery.fn.init.prototype = jQuery.fn时,用构造函数jQuery()的原型对象覆盖了构造函数jQuery.fn.init()的原型对象,从而使构造函数jQuery.fn.init()的实例也可以访问构造函数jQuery()的原型方法和属性。

4)为什么要把第25~955行的代码包裹在一个自调用匿名函数中,然后把第25行定义的构造函数jQuery()作为返回值赋值给第22行的jQuery变量?去掉这个自调用匿名函数,直接在第25行定义构造函数jQuery()不也可以吗?去掉了不是更容易阅读和理解吗?

去掉第25~955行的自调用匿名函数当然可以,但会潜在地增加构造jQuery对象模块与其他模块的耦合度。在第25~97行之间还定义了很多其他的局部变量,这些局部变量只在构造jQuery对象模块内部使用。通过把这些局部变量包裹在一个自调用匿名函数中,实现了高内聚低耦合的设计思想。

5)为什么要覆盖构造函数jQuery()的原型对象jQuery.prototype?

在原型对象jQuery.prototype上定义的属性和方法会被所有jQuery对象继承,可以有效减少每个jQuery对象所需的内存。事实上,jQuery对象只包含5种非继承属性,其余都继承自原型对象jQuery.prototype;在构造函数jQuery.fn.init()中设置了整型属性、length、selector、context;在原型方法.pushStack()中设置了prevObject。因此,也不必因为jQuery对象带有太多的属性和方法而担心会占用太多的内存。

关于构造函数、原型、继承等基础知识,请查阅相关的基础类书籍。

相关文章
|
1月前
|
设计模式 前端开发 测试技术
Flutter 项目架构技术指南
探讨Flutter项目代码组织架构的关键方面和建议。了解设计原则SOLID、Clean Architecture,以及架构模式MVC、MVP、MVVM,如何有机结合使用,打造优秀的应用架构。
Flutter 项目架构技术指南
|
1月前
|
算法 数据挖掘 调度
隐语实训营-第3讲:详解隐私计算框架的架构和技术要点
主要介绍隐语的隐私计算架构,并对每个模块进行拆解、分析,以期望不同使用者找到适合自己的模块,快速入手。
48 4
|
1月前
|
分布式计算 算法 调度
课3-详解隐私计算框架的架构和技术要点
隐语架构涵盖产品、算法、计算、资源和硬件五层,旨在实现互联互通和跨域管控。产品层包括SecretPad等,简化用户和集成商体验。算法层涉及PSI/PIR、SCQL和联邦学习,提供隐私保护的数据分析和学习。计算层如RayFed、SPU、HEU等,支持分布式计算和密态处理。资源层的KUSCIA用于跨机构任务编排,硬件层涉及FPGA等加速器。互联互通支持黑盒和白盒模式,确保不同平台协作。跨域管控则强调数据流转控制,保护数据权益。
|
28天前
|
设计模式 安全 Java
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
32 0
|
19天前
|
存储 编译器 Linux
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
|
1月前
|
机器学习/深度学习 算法 安全
隐私计算训练营第三讲-详解隐私计算的架构和技术要点
SecretFlow 是一个隐私保护的统一框架,用于数据分析和机器学习,支持MPC、HE、TEE等隐私计算技术。它提供设备抽象、计算图表示和基于图的ML/DL能力,适应数据水平、垂直和混合分割场景。产品层包括SecretPad(快速体验核心能力)和SecretNote(开发工具)。算法层涉及PSI、PIR、数据分析和联邦学习(水平、垂直、混合)。此外,SecretFlow还有YACL密码库和Kusica任务调度框架,Kusica提供轻量化部署、跨域通信和统一API接口。
50 0
|
28天前
|
NoSQL Java Redis
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的分布式锁的功能组件(二)
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的分布式锁的功能组件
15 0
|
19天前
|
存储 算法
【算法与数据结构】深入解析二叉树(二)之堆结构实现
【算法与数据结构】深入解析二叉树(二)之堆结构实现
|
27天前
|
存储 监控 安全
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
63 1

推荐镜像

更多