首先说明这不是一篇完整解读ExtJS和jQuery所有方面差异的文章,只是针对我个人刚看了两天的jQuery产生的一些疑问的整理。之前用过一段时间ExtJS,了解ExtJS的一些机制。现在做移动开发,又选定了jquery mobile,要写控件,所以需要了解jquery。(不过换工作之后应该不会再用jQuery了,坑估计是短期内填不上了)

1、jQuery是个什么东西?Ext是什么东西?(此处不是指两个框架,而是指我们在写程序的时候,经常用到的两个关键字--暂时称之为关键字)

之前用的是ExtJS,Ext是个Object,通过字面量创建的,Ext.js文件里,3.3.1版:

  1. Ext = {
  2. version : '3.3.1',
  3. versionDetail : {
  4. major : 3,
  5. minor : 3,
  6. patch : 1
  7. }
  8. };

4.0版本,此处global == window:

  1. if (typeof Ext === 'undefined') {
  2. global.Ext = {};
  3. }

既然Ext是个Object,那jQuery是不是也是个Object呢?NO,来分析下源码,jquery.js:

  1. var jQuery = (function() {
  2. // Define a local copy of jQuery
  3. var jQuery = function( selector, context ) {
  4. // The jQuery object is actually just the init constructor 'enhanced'
  5. return new jQuery.fn.init( selector, context, rootjQuery );
  6. },
  7. ...//此处省略900行
  8. return jQuery;
  9. })();

此处大概明白了,jQuery是个Function,并且由于此处调用jQuery的时候,有个return,所以var v = jQuery(xxx)和var v = new jQuery(xxx)调用后,v都是同一个函数的实例。在《JavaScript高级程序设计》第18章第一节有提到过这种技巧,叫做作用域安全的构造函数,不过书上提到的形式稍有差异:

  1. function Person(name,age){
  2. if(this instanceof Person){
  3. this.name = name;
  4. this.age = age;
  5. }else{
  6. return new Person(name,age);
  7. }
  8. }

这样var p = Person('a',21)和var p = new Person('a',21) ,p就都是Person实例了,如果去掉if判断和else后边的内容,第一种调用p是undefined。

在jquery.js最后,把变量jQuery赋值给了$,后续可以通过$这种简写使用jQuery,算是一个简写的别名吧:

  1. window.jQuery = window.$ = jQuery;

此处先挖个坑,构造函数中(如此处的Person)的this到底怎么理解?

2、jQuery和Ext在这两个关键字都怎么使用的,有何异同?

2.1、Ext是个对象,是一个命名空间,跟java里头的package类似,使用Ext下边的方法、Function/类的时候,就像使用一个对象的属性一样,如工具方法Ext.apply、Ext.applyIf可以直接调用,构造函数Ext.json.DataStore,前边加new创建实例。关于这么做的好处,了解java package的好处的都知道那么一些吧,我只还记得避免命名冲突。

2.2、jQuery首先是个Function,既然是个Function,那个就可以new,可以像Function一样调用,以下将解析几种jQuery调用方法的源码:

jQuery(xxx)的时候,转调到

  1. new jQuery.fn.init(selector,context,rootjQuery)

具体调用时候就需要分析jQuery.prototype.init函数了。

2.2.1、jQuery(function(){}),当传入是function的时候,init方法片段:

  1. else if ( jQuery.isFunction( selector ) ) {
  2. return rootjQuery.ready( selector );
  3. }

此处rootjQuery默认又等于jQuery(document);ready实际上就是在为document注册load事件,源码:

  1. ready: function( fn ) {
  2. // Attach the listeners
  3. jQuery.bindReady();
  4. // Add the callback
  5. readyList.done( fn );
  6. return this;
  7. }

bindReady方法是通过attachEvent/addEventListener为document注册了load事件。

  1. bindReady: function() {
  2. if ( readyList ) {
  3. return;
  4. }
  5. readyList = jQuery._Deferred();
  6. // Catch cases where $(document).ready() is called after the
  7. // browser event has already occurred.
  8. if ( document.readyState === "complete" ) {
  9. // Handle it asynchronously to allow scripts the opportunity to delay ready
  10. return setTimeout( jQuery.ready, 1 );
  11. }
  12. // Mozilla, Opera and webkit nightlies currently support this event
  13. if ( document.addEventListener ) {
  14. // Use the handy event callback
  15. document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
  16. // A fallback to window.onload, that will always work
  17. window.addEventListener( "load", jQuery.ready, false );
  18. // If IE event model is used
  19. } else if ( document.attachEvent ) {
  20. // ensure firing before onload,
  21. // maybe late but safe also for iframes
  22. document.attachEvent( "onreadystatechange", DOMContentLoaded );
  23. // A fallback to window.onload, that will always work
  24. window.attachEvent( "onload", jQuery.ready );
  25. ……
  26. }
  27. }

2.2.2、jQuery(DOMElement)当传入参数是一dom element的时候,init方法片段:

  1. if ( selector.nodeType ) {
  2. this.context = this[0] = selector;
  3. this.length = 1;
  4. return this;
  5. }

把dom元素放到了new出来的init对象上,此处this应该是一个对象,应该是个Object的,但是从Chrome调试看,此时this竟然显示为jQuery.fn.jQuery.init[0],Object.prototype.toString.call(this)结果是”[object Object]”,是个对象,为何显示这么奇怪呢?在FF里,this显示为[],按照道理说,对象应该不会这么显示的才对。

此处把元素赋值为this[0]可以在后续访问元素的时候,直接用返回实例的[0]来访问,如果是多个元素,则可以用下标一个个的访问,后边看到selector的时候会看到。同时由于后边把init的原型指向了jQuery的原型,所以这里this的原型方法都是jQuery.prototype的方法:

  1. jQuery.fn = jQuery.prototype = ……
  2. jQuery.fn.init.prototype = jQuery.fn;

挖坑,关于原型方法,实例的关系。

2.2.3、如果传入是body,jQuery(“body”),返回只有一个body元素

  1. if ( selector === "body" && !context && document.body ) {
  2. this.context = document;
  3. this[0] = document.body;
  4. this.selector = selector;
  5. this.length = 1;
  6. return this;
  7. }

2.2.4、jQuery(selector),如jquery.mobile.js中initializePage中$(“:jqmData(role=’page’)”)

  1. // Handle HTML strings
  2. if ( typeof selector === "string" ) {
  3. // Are we dealing with HTML string or an ID?
  4. if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
  5. // Assume that strings that start and end with <> are HTML and skip the regex check
  6. match = [ null, selector, null ];
  7. } else {
  8. match = quickExpr.exec( selector );
  9. }
  10. // Verify a match, and that no context was specified for #id
  11. if ( match && (match[1] || !context) ) {
  12. ……//省略几十行,这一段是避免xss攻击什么的,没读懂,以后再来读
  13. return this;
  14. }
  15. // HANDLE: $(expr, $(...))
  16. } else if ( !context || context.jquery ) {
  17. return (context || rootjQuery).find( selector );
  18. // HANDLE: $(expr, context)
  19. // (which is just equivalent to: $(context).find(expr)
  20. } else {
  21. return this.constructor( context ).find( selector );
  22. }
  23. }

如果传入的context为空,就从当前对象查找find(selector)否则就从rootjQuery查找,这里rootjQuery是个实力,所以此方法调用就是调用的原型上的find方法:

  1. jQuery.fn.extend({
  2. find: function( selector ) {
  3. var self = this,
  4. i, l;
  5. ……//此处省略10+行
  6. var ret = this.pushStack( "", "find", selector ),
  7. length, n, r;
  8. for ( i = 0, l = this.length; i < l; i++ ) {
  9. length = ret.length;
  10. jQuery.find( selector, this[i], ret );
  11. if ( i > 0 ) {
  12. // Make sure that the results are unique
  13. for ( n = length; n < ret.length; n++ ) {
  14. for ( r = 0; r < length; r++ ) {
  15. if ( ret[r] === ret[n] ) {
  16. ret.splice(n--, 1);
  17. break;
  18. }
  19. }
  20. }
  21. }
  22. }
  23. return ret;
  24. }

此处又调用到了jQuery.find方法,注意,jQuery是一个Function,这个find跟rootjQuery不同,jQuery.find是function的一个属性,非严格意义上可以简单的认为类似于java的静态方法。此find方法实则是Sizzle本身:

jQuery.find = Sizzle;

具体实现还要看selector的内容,可能是getTagByName或者querySelectorAll,如getTagByName(‘name’)、querySelectorAll(“[data-role=’page’]”)。

2.2.5、jQuery()如果传入为空,则返回不包含元素的jQuery对象:

  1. if (!selector ) {
  2. return this;
  3. }

2.2.6、jQuery(jQuery()),也就是传一个jQuery实例进去,会创建一个新对象,然后把老对象的内容拷贝到新对象里头。

综上,jQuery()返回的是一个jQuery.prototype.init函数的实例,但是由于这个函数的原型指向了jQuery函数的原型,jQuery.prototype上的方法也可以直接在这个实例上调用。同时jQuery会被当成一个数组来使用,根据下标索引提取满足参数的dom元素。

2.3、jQuery接着:-)也起到命名空间的作用。

虽然jQuery是个function,但是可以在function上添加属性(这么叫准确么?)然后就可以直接jQuery.method()、jQuery.filed的调了。这里jQuery至少起到了一个命名空间的作用。

既然说到命名空间了,就不得不说jQuery的原型和function的方法,jQuery.method()类似静态方法,可以通过

  1. jQuery.method=function(){}
  2. jQuery.extend({method:function(){}})

两种方法来添加。原型方法则通过jQuery.fn.extend / jQuery.prototype.extend来添加。

3、jQuery和Ext都怎么实现继承的,有什么异同?各有什么优势?

JavaScript是一门基于对象的语言,但不是面向对象,也就是说语言层面没有提供继承的语法,但是可以通过应用层面实现继承。由于把这种实现放到了应用层面,所以实现就变得五花八门了,可以通过拷贝、原型链等。了解两种继承的调用方式对理解下边说到的实现原理是很有帮助的。

3.1、Ext(3.x)的继承跟《JavaScript高级程序设计》里讲到的寄生组合模式类似,这种实现方式复杂,不太容易理解。具体是在当前类和超类之间插入一个空对象,作为子类的原型对象,这个空对象的构造函数的原型指向超类的原型,然后把子类的方法,全部放入到这个空对象上。这样可以做到方法通过原型链实现继承,实例属性通过借用构造函数实现继承。这种方法也是目前最完美的实现方案。ExtJS继承的源码解析参考这里

3.2、jQuery的继承的实现是基于拷贝的,这种实现比较简单,容易理解。但是要注意的是,jQuery这个function本身和jQuery的原型都有继承方法,其中jQuery.extend是把方法、属性拷贝到function上,后续可以直接通过jQuery.method调用;jQuery.fn.extend是把方法、属性拷贝到jQuery的原型上,后续可以通过jQuery实例(实际是jQuery.fn.init的实例,这个init函数的原型指向jQuery的原型)调用:

  1. jQuery.extend = jQuery.fn.extend = function() {
  2. var options, name, src, copy, copyIsArray, clone,
  3. target = arguments[0] || {}, i = 1,
  4. length = arguments.length, deep = false;
  5. // Handle a deep copy situation
  6. if ( typeof target === "boolean" ) {
  7. deep = target;
  8. target = arguments[1] || {};
  9. // skip the boolean and the target
  10. i = 2;
  11. }
  12. // Handle case when target is a string or something (possible in deep copy)
  13. if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
  14. target = {};
  15. }
  16. // extend jQuery itself if only one argument is passed
  17. if ( length === i ) {
  18. target = this;//如果参数只有一个,target就指向this
  19. --i;
  20. }
  21. for ( ; i < length; i++ ) {
  22. // Only deal with non-null/undefined values
  23. if ( (options = arguments[ i ]) != null ) {
  24. // Extend the base object
  25. for ( name in options ) {//开始复制
  26. src = target[ name ];
  27. copy = options[ name ];
  28. // Prevent never-ending loop
  29. if ( target === copy ) {
  30. continue;
  31. }
  32. // Recurse if we're merging plain objects or arrays
  33. if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  34. if ( copyIsArray ) {
  35. copyIsArray = false;
  36. clone = src && jQuery.isArray(src) ? src : [];
  37. } else {
  38. clone = src && jQuery.isPlainObject(src) ? src : {};
  39. }
  40. // Never move original objects, clone them
  41. target[ name ] = jQuery.extend( deep, clone, copy );
  42. // Don't bring in undefined values
  43. } else if ( copy !== undefined ) {
  44. target[ name ] = copy;
  45. }
  46. }
  47. }
  48. }
  49. // Return the modified object
  50. return target;
  51. };

需要特别注意的是这个this,当jQuery.extend的时候,this指的是jQuery.fn.init这个function,后续的方法、属性复制是复制给function的;当通过jQuery.fn.extend的时候,this指向的是原型对象,后续的方法、属性复制是复制给了原型对象。

ExtJS与jQuery的一点细节上的对比的更多相关文章

  1. ExtJs4 笔记(1) ExtJs大比拼JQuery:Dom文档操作

    现在主流的JS框架要数ExtJs和JQuery应用的比较广泛.JQuery属于轻量级的,一般做网站应用比较常见,可见块头小的优势.ExtJs比较庞大,它除了对基本的JS语法和HTML DOM操作方式的 ...

  2. [转载]ExtJs4 笔记(1) ExtJs大比拼JQuery:Dom文档操作

    出处:[Lipan] (http://www.cnblogs.com/lipan/) 现在主流的JS框架要数ExtJs和JQuery应用的比较广泛.JQuery属于轻量级的,一般做网站应用比较常见,可 ...

  3. ExtJS与JQuery对照

    首先在介绍ExtJS和JQuery,然后进行比较 一个.什么是ExtJS? 1.ExtJS能够用来开发RIA也即富client的AJAX应用,是一个用javascript写的,主要用于创建前端用户界面 ...

  4. jQuery文件上传插件jQuery Upload File 有上传进度条

    jQuery文件上传插件jQuery Upload File 有上传进度条 jQuery文件上传插件jQuery Upload File,插件使用简单,支持单文件和多文件上传,支持文件拖拽上传,有进度 ...

  5. 【转】JQuery插件ajaxFileUpload 异步上传文件(PHP版)

    前几天想在手机端做个异步上传图片的功能,平时用的比较多的JQuery图片上传插件是Uploadify这个插件,效果很不错,但是由于手机不支持flash,所以不得不再找一个文件上传插件来用了.后来发现a ...

  6. jQuery模拟原生态App上拉刷新下拉加载

    jQuery模拟原生态App上拉刷新下拉加载效果代码,鼠标上拉时会显示loading字样,并且会模拟加载一条静态数据,支持触屏设备使用. <!doctype html> <html ...

  7. 转: 如何实现jQuery的Ajax文件上传

    [PHP文件上传] 在开始之前,我觉得是有必要把通WEB上传文件的原理简单说一下的.实际上,在这里不管是PHP,JSP,还是ASP处理上传的文件,其实都是WEB早已把文件上传到服务器了,我们只是运用上 ...

  8. jQuery插件AjaxFileUpload文件上传实现Javascript多文件上传功能

     Ajax file upload plugin是一个功能强大的文件上传jQuery插件,可自定义链接.或其它元素庖代传统的file表单上传结果,可实现Ajax动态提示文件上传 过程,同时支撑多文 ...

  9. jquery组件WebUploader文件上传用法详解

    这篇文章主要为大家详细介绍了jquery组件WebUploader文件上传用法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 WebUploader是由Baidu WebFE(FEX)团队开发的一 ...

随机推荐

  1. ace 读取excel

    insert into T_BirdSystemSku(ID,Sku) select ID,SKU from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel ...

  2. jQuery学习笔记(2)

    val() 当鼠标放上去的时候,文本消失,鼠标拿开,文本恢复 效果图: code as below: <html xmlns="http://www.w3.org/1999/xhtml ...

  3. java基础笔记

    1. 成员变量会自动的进行初始化,但是局部变量不会: 2. equals传引用值,==传地址值:当一个对象是引用类型时,就必须使用equals进行比较. 3. 继承:实现代码的复用,继承关系以一种验证 ...

  4. spring AOP advice 类型 和 通用的切点的配置方式

    spring aop advice的类型: 1.前置通知(before advice) 2.返回后通知(after returning advice) 3.抛出异常后通知(after throwing ...

  5. bzoj 1862/1056 [HAOI2008]排名系统

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862 很恶心的 一道题,我也不晓得自己是第几次写这题了%>_<%. 写了两种方 ...

  6. Amazon Kindle Device is hiring in Beijing Shanghai and Shenzhen!

    This is Angela from recruitment team of Amazon Kindle Device Software & Applications, we are exp ...

  7. 微软云平台媒体服务实践系列 2- 使用动态封装为iOS, Android , Windows 等多平台提供视频点播(VoD)方案

    文章微软云平台媒体服务实践系列 1- 使用静态封装为iOS, Android 设备实现点播(VoD)方案  介绍了如何针对少数iOS, Android 客户端的场景,出于节约成本的目的使用媒体服务的静 ...

  8. SecurityManager一:理解AccessController.doPrivileged()

    AccessController.checkPermission()检测模型: 从VM Stack的current stack frame起逐个检测stack frome所指class的protect ...

  9. WCF note1

    Summary of WCF Client to use service use ChannelFactory to create proxy to use service. Client code ...

  10. verilog运算符及表达式

    1.运输符 算术运算符(+,-,X,/,%) 赋值运算符(=,<=) 关系运算符(>,<,>=,<=) 逻辑运算符(&&,||,!)//与或非 条件运算符 ...