`
lcyangily
  • 浏览: 21842 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

jQuery源码分析之整体框架分析

阅读更多

 

    读一个开源框架,大家最想学到的就是设计的思想和实现的技巧。最近读jQuery源码,记下我对大师作品的理解和心得,跟大家分享,权当抛砖引玉。

 

先附上jQuery的代码结构。

 

 

(function(){
    //jQuery变量定义
    var jQuery  = function(){...};
    //jQuery原型定义(包含核心方法)              
    jQuery.fn = jQuery.prototype = {...};
    //看上去很奇怪吧? 非常巧妙的设计,后面详细介绍
    jQuery.fn.init.prototype = jQuery.fn;
    //提供jQuery静态方法与对象方法的扩展函数
    jQuery.extend = jQuery.fn.extend = function(){...}; 
    //后面依次有多个对jQuery静态方法的扩展
    jQuery.extend({...});
    //后面依次有多个对jQuery对象方法的扩展
    jQuery.fn.extend({...});
    jQuery.support = (function() {...})();
    //提供统一时间管理,jQuery内部使用,并不对外开放
    jQuery.event = {...};
    //Event类似于Java的POJO类.传递事件的对象
    jQuery.Event = function( src, props ) {...}; 
    //Sizzle选择器,一个框架,可独立使用。
    (function(){
        ...
        jQuery.find = Sizzle;
        ...
    })();
    ...
    //将定义的jQuery定义为全局变量
    window.jQuery = window.$ = jQuery;
    ...
})();

 

 

 

在结构上非常的清晰,定义一个jQuery对象,对jQuery对象进行扩展,赋给window,变成全局变量。就以下几点做介绍:

1). 自执行的匿名函数。

2). $("...")形式调用返回 jQuery.fn.init对象。

3). 框架里最常见的 extend 函数。

 

一. 自执行匿名函数。

对javascript有一定基础的都应该知道自执行匿名函数的好处。js是函数作用域。在函数里定义的变量都是局部变量,这样就很好的避免了过多的全局变量(jQuery仅仅2个全局变量jQuery和$)。由于闭包属性,虽然函数自执行结束了,但自执行函数里面定义的局部函数和变量还是能够被定义成全局变量的jQuery和$所引用到,类似于Java的私有变量。好处可见一斑。

 

二. $("...")形式调用返回 jQuery.fn.init对象。

这是我刚看源码的时候最不理解的地方。

 

var jQuery = function( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
}
和
jQuery.fn.init.prototype = jQuery.fn;
看懂这段我们先看看jQuery的使用。jQuery采用链式调用(如:$("#id").data("xxx")),这样就知道$("#id")返回的是一个jQuery对象。但是调用的方式是函数调用。这个问题就成为了:以函数的方式调用返回jQuery对象,并且构造函数是init。现在就围绕解决这个问题展开:
首先想到的是在函数式调用的时候返回一个jQuery对象。
var jQuery = function( selector, context ) {
    return new jQuery( selector, context);
}
兄弟,你确定这样? 明眼人一看就知道严重的问题所在,死递归!
既然不能调用本身,那我们想到另一种办法:再定义一个函数A,A的原型与jQuery的原型一样,那A的对象与jQuery生成的对象就是一模一样了(javascript是原型继承),而且将A的constructor定义为jQuery,上面的问题不是迎刃而解么?
 
var jQuery = function( selector, context ) {
    return new A( selector, context);
}

var A = function(){
    if(this.init) {
        this.init();
    }
};
A.prototype = jQuery.prototype;

这样就解决了上面的问题,因为jQuery和A拥有同一个原型,所以生成的对象都拥有相同的方法。但是还是感觉A定义的有些多余,是不是?
既然定义A就为了返回A的对象,那init函数也能生成对象(以为js中没有类,定义的函数可以当函数执行,也能new成对象)。既然用init的话,那样init函数会自动执行,也不用再调用,岂不是更方便!所以就看到了我们之前看到的代码。
这里可能还有个fn解释下,其实这个fn没有什么特殊意思,只是jQuery.prototype的引用,jQuery支持自己扩展属性,这个对外提供了一个接口,jQuery.fn.extend()来对对象增加方法,比使用jQuery.prototype.extend()更好。封装想,字面就能看懂是对函数扩展,而不是看上去直接修改prototype.友好的用户接口。
相对于文字,图形化更加直观,对上面的引用来引用去画了个图,更好的理解:


其实在使用返回 new jQuery.fn.init( selector, context, rootjQuery ) 对象方式,我还有另一种实现
var jQuery = function( selector, context ) {
    //如果以$("#id") 方式调用this就不是jQuery.这样返回jQuery对象
    if(!(this instanceof jQuery)) {
        return new jQuery(selector, context);
    }
    if(this.init) {
        this.init();
    }
}
//这行就可以注释了
//jQuery.fn.init.prototype = jQuery.fn;
 
这种经过测试时可以的,不知道还有没有其他的隐蔽问题,暂时没发现,也算是一种实现吧。供大家参考。
三. 框架里最看到的 extend 函数
在后面的段落中有大段大段的 jQuery.extend({...}) 和 jQuery.fn.extend({...}) 代码。这里先解释下这个的作用和不同。
extend 在java中是继承,在我之前写的一篇 <简单实现Javascrip继承> 文章不同,也都是用了extend关键字。那些我们都说叫继承,而这里我更加喜欢叫扩展。为什么呢? 继承是产生了新的类,而这里没有,这里的2个函数第一个是扩展jQuery的静态方法,而第二个是用户自己扩展对象的方法。静态方法?对象方法?这里我来做个解释,在jQuery中有2中调用形式:
1)$.Ajax(...);
2)$("#id").data("xxx");
第一种调用我称为静态调用,就类似于Java的静态方法一样,不用生成对象,而是类级函数。这里的$就相当于命名空间一样。我们知道在以往js的编程中,如果有命名空间我们都这样:
var ns = {};
ns.Ajax = function(){...};
那为什么这里不是对象,而是函数做一个命名空间呢? 其实在js中一切都是对象!包括函数也是对象(说Java一切都是对象,我觉得其实这句话形容js更加贴切)。
第二种调用我成为对象调用,因为.data()方法是定义在原型中的,只有new个对象才能调用的,所以成为对象方法。
我们看代码jQuery.extend = jQuery.fn.extend = function(){...}; 这个是连等,也就是2个指向同一个函数,怎么会实现不同的功能呢?这就是this 的功能了。jQuery.extend 调用的时候,this是指向jQuery对象的(jQuery是函数,也是对象!),所以这里扩展在jQuery上。 而jQuery.fn.extend 调用的时候,this指向fn对象,而上图中科院看到,jQuery.fn 和jQuery.prototype指向同一对象,扩展fn就是扩展jQuery.prototype原型对象。这里增加的是原型方法,也就是对象方法了。所以jQuery的api中提供了以上2中扩展函数。
本章结束,有不对和不准确的地方望大家指正。有疑问可以留言。
下篇介绍jQuery的data实现。欢迎关注。
分享到:
评论

相关推荐

    jQuery 2.0.3 源码分析之core(一)整体架构

    废话不多说,jquery这么多年了分析都写烂了,老早以前就拜读过, 不过这几年都是做移动端,一直御用zepto, 最近抽出点时间把jquery又给扫一遍 我也不会照本宣科的翻译源码,结合自己的实际经验一起拜读吧! github上...

    《精通Javascript+jQuery》光盘源码

    第1部分 JavaScript.cCSS与DOM基础篇   第1章 ccJavaScript概述  1.1 JavaScript的起源  1.2 浏览器之争  1.2.1 DHTML  1.2.2 浏览器之间的冲突 ...第3部分 jQuery框架篇 第4部分 综合案例篇

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ │ 13.RPC底层通讯原理之Netty线程模型源码分析.wmv │ │ │ ├─14.分库分表之后分布式下如何保证ID全局唯一性 │ │ 14.分库分表之后分布式下如何保证ID全局唯一性.mp4 │ │ │ └─15.大型公司面试必答之...

    jquery的总体架构分析及实现示例详解

    学习开源框架,童鞋们最想学到的就是设计的思想和实现的技巧。最近研究jQuery源码,记录一下我对jquery的理解和心得,跟大家分享,权当抛砖引玉。

    WEB开发必备几乎包含所有参考资料

    ppt),Jquery1.2.6源码分析,Linux常用命令全集,linux入门文档,MySQL中文参考手册,PHP_MySQL教程,PHP的一些例程,PHP的一些例程,prototype,Spring+in+Action中文版,SQL Server精华 (CHM),Struts快速学习指南,Validato...

    北风客户关系管理源码 CRM

    再加上设计轻巧的JQuery框架,一个完美的整合框架由此而生。 3.真实的案例 该案例是一个价值6万元的项目,当然在功能和工作量上有部分缩水,但是技术绝对不会缩水。 4.项目中技术点: 该项目中的技术点可谓众多,每个...

    基于Python的qixqi排行榜数据及网页数据展示系统.zip

    数据 flask 框架展示部分:主要使用到了 flask、jQuery、echarts、CSS 技术来将数据合理美观的展示在网页中,实现了项目需求分析的要求,该部分的 flask 框架并不难掌握,重点是使用模版来响应 HTML 格式的网页信息...

    SSM后台管理系统开发实战

    一、简介 通过这个课程带大家从零开发一款功能全面的后台管理系统,包括项目搭建、功能实现到最后的Linux系统部署全过程。本课程使用SpringMVC + Spring + Mybatis作为主体框架,...SpringMVC源码分析Mybatis源码分析

    单点登录源码

    单点登录, SSM框架公共模块 ├── zheng-admin -- 后台管理模板 ├── zheng-ui -- 前台thymeleaf模板[端口:1000] ├── zheng-config -- 配置中心[端口:1001] ├── zheng-upms -- 用户权限管理系统 | ├── ...

    SpringBoot企业级博客系统(未加密+源码)

    本节先从Bootstrap 的基本原理讲起,并将常用的前端框架比如 JQuery等进行集成。最后通过一个实战内容,来帮助学员理解掌握。 第10章 博客系统的需求分析与原型设计 本章节是对博客系统的需求分析与设计。对于企业...

    SSM项目的宝康药房销售管理系统.zip

    2. **技术实现**:项目利用了SSM框架中的Spring进行整体的业务管理,SpringMVC负责前后端的交互和页面跳转,而MyBatis则处理与数据库的交互。这样的技术栈确保了系统的稳定运行和高效性能。 3. **前后端分离**:前端...

    大数据培训课程安排.pdf

    主要技术包括:Hibernate、Spring、SpringMVC、log4j slf4j 整合、myBatis、struts2、Shiro 、redis、流程引擎activity, 爬 ⾍技术nutch,lucene,webService CXF、Tomcat集群和热备 、MySQL读写分离 4. 描述如下:...

    Lerx 网站内容管理系统 v5.5.zip

    主要采用Jquery 1.9.1,使用Layui 2模块化前端框架。 Jquery Layui JSON Ajax Lerx 网站内容管理系统主要功能 前后台用户及角色管理、站点管理、栏目、文章管理、模板管理、自由开放的模板市场、系统监测、调查...

Global site tag (gtag.js) - Google Analytics