读一个开源框架,大家最想学到的就是设计的思想和实现的技巧。最近读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源码中Callbacks模块的内部实现之前,先要明确什么是Callbacks以及它在JavaScript编程中的作用。Callbacks,即回调函数,在JavaScript中扮演着至关重要的角色。由于JavaScript是基于单线程事件循环...
《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。对于深入理解JavaScript和前端开发技术的开发者来说,探究jQuery的源码是提升技能的重要途径...
### jQuery源码+中文详细注解 #### 一、引言 本文档是对jQuery源码进行中文注解的详细介绍,旨在帮助广大前端开发者更深入地理解jQuery的核心逻辑和技术要点。通过对核心部分的逐行注解,可以更好地掌握jQuery的...
通过以上对jQuery源码的部分分析,我们可以看出jQuery在设计上考虑了兼容性、性能以及安全性,采用了大量的正则表达式进行字符串和DOM元素的处理,并提供了丰富的工具函数和API来简化JavaScript的编程工作。
在深入探讨jQuery 2.0.3源码中core部分的整体架构之前,我们先简要回顾一下jQuery框架的核心功能和其设计思想。jQuery是一个广泛使用的JavaScript库,主要用于简化HTML文档遍历和操作、事件处理、动画和Ajax交互。它...
SSH框架是Java Web开发中常用的一套高效、轻量级的整合框架,用于构建企业级的MVC(Model-View-Controller)应用。而jQuery则是JavaScript库,简化了DOM操作、事件处理和动画制作,极大地提高了前端开发效率。 **...
`1.3.5` 是这个框架的一个版本,我们接下来将深入探讨其核心概念、主要功能以及源码分析。 1. **jQuery EasyUI 核心概念** - **jQuery**:EasyUI 基于 jQuery 构建,jQuery 是一个快速、简洁的JavaScript库,用于...
《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。本项目旨在深入解析jQuery的源码,通过分段解析、添加全中文注释和制作成手册的方式,帮助...
此源码可以作为学习C# ASP.NET和Jquery结合开发的实例,帮助开发者了解如何在实际项目中整合这两种技术。通过阅读和分析这些源码,可以提升对于Web应用架构设计、数据库交互、前后端通信以及客户端脚本优化的理解。...
9. **扩展与集成**:jQuery Gantt可能与其他库(如Bootstrap、AngularJS等)兼容,以便于整合到现有的Web框架中。此外,还可以通过编写自定义插件或扩展来增加新的功能。 10. **性能优化**:对于大型项目,加载和...
源码分析可以帮助开发者理解EasyUI如何处理事件、渲染DOM元素、以及与jQuery的交互方式,对于性能优化和扩展功能很有价值。 ### 演示示例 (`jquery-easyui-DEMO`) `jquery-easyui-DEMO` 文件夹提供了各种组件的使用...
"jQuery-starterkit源码"是一套为初学者和开发者提供的基础框架,旨在帮助他们快速理解和构建基于jQuery的Web应用。这份资料包含了必要的文件和代码示例,以便于深入学习和实践。 首先,`ratings.dat`可能是一个...
jQuery Mobile 是一个用于构建响应式网页和移动应用的框架,它基于 jQuery 库,专注于提供一致且易用的用户界面,适用于多种设备,包括智能手机、平板电脑以及桌面浏览器。jQuery Mobile 的核心理念是“Write less, ...
10. **源码分析与定制**:对于高级开发者,可以深入研究jquery.lazy-master目录中的源代码,理解其实现原理,并根据项目需求进行定制或扩展。 总的来说,"前端项目-jquery.lazy"是一个实用的前端工具,旨在提升网页...
通过分析和实践这个项目,你可以深入理解SSM框架的工作原理,掌握如何将它们整合到实际项目中,以及如何利用jQuery优化用户交互。同时,你还可以学习到如何使用CSS来美化和布局管理界面,提升Web应用的视觉体验。
jQuery EasyUI 是一个基于 jQuery 的前端框架,它提供了丰富的组件和便捷的API,用于快速构建交互式的Web应用。EasyUI 1.5.3 版本的源代码是开发者深入理解其内部工作原理、定制功能以及优化性能的重要参考资料。...
### ABP源码分析 #### 一、整体项目结构及目录 ABP作为一个高度模块化且灵活可扩展的Web应用程序框架,其设计思路和技术选型都极具参考价值。本章节将着重探讨ABP项目的整体结构及其各个组成部分的功能定位。 ###...
jQuery EasyUI 还支持主题定制,可以通过更换皮肤文件轻松改变应用的整体风格。此外,框架的API设计友好,使得开发者可以方便地进行事件绑定、方法调用和属性设置,以实现复杂的功能需求。 在学习jQuery EasyUI的...
5. **源码分析**:源码分析可以帮助我们理解各个组件如何协同工作。Action类处理HTTP请求,Service层包含业务逻辑,DAO层负责与数据库交互。此外,还有可能涉及JSP或Freemarker等视图技术,以及JavaScript和jQuery来...