`

ExtJS与jQuery的一点细节上的对比

阅读更多

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

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

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

Ext = {
 version : '3.3.1',
 versionDetail : {
  major : 3,
  minor : 3,
  patch : 1
 }
}; 

      4.0版本,此处global == window:

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

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

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

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

function Person(name,age){
   if(this instanceof Person){
      this.name = name;
      this.age = age;
   }else{
      return new Person(name,age);
   }
}

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

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

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)的时候,转调到

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

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

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

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

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

     ready: function( fn ) {
           // Attach the listeners
           jQuery.bindReady();
           // Add the callback
           readyList.done( fn );
           return this;
        }

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

  bindReady: function() {
       if ( readyList ) {
           return;
       }
       readyList = jQuery._Deferred();
       // Catch cases where $(document).ready() is called after the
       // browser event has already occurred.
       if ( document.readyState === "complete" ) {
           // Handle it asynchronously to allow scripts the opportunity to delay ready
           return setTimeout( jQuery.ready, 1 );
       }
       // Mozilla, Opera and webkit nightlies currently support this event
       if ( document.addEventListener ) {
           // Use the handy event callback
           document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
           // A fallback to window.onload, that will always work
           window.addEventListener( "load", jQuery.ready, false );
       // If IE event model is used
       } else if ( document.attachEvent ) {
           // ensure firing before onload,
           // maybe late but safe also for iframes
           document.attachEvent( "onreadystatechange", DOMContentLoaded );
           // A fallback to window.onload, that will always work
           window.attachEvent( "onload", jQuery.ready );
           ……
       }
    }

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

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

    把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的方法:

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

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

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

if ( selector === "body" && !context && document.body ) {
    this.context = document;
    this[0] = document.body;
    this.selector = selector;
    this.length = 1;
    return this;
}

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

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

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

jQuery.fn.extend({
    find: function( selector ) {
       var self = this,
           i, l;
       ……//此处省略10+行
       var ret = this.pushStack( "", "find", selector ),
           length, n, r;
       for ( i = 0, l = this.length; i < l; i++ ) {
           length = ret.length;
           jQuery.find( selector, this[i], ret );
           if ( i > 0 ) {
              // Make sure that the results are unique
              for ( n = length; n < ret.length; n++ ) {
                  for ( r = 0; r < length; r++ ) {
                     if ( ret[r] === ret[n] ) {
                         ret.splice(n--, 1);
                         break;
                     }
                  }
              }
           }
       }
       return ret;
}

     此处又调用到了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对象:

if (!selector ) {
      return this;
}

       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()类似静态方法,可以通过

jQuery.method=function(){}
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的原型)调用:

jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
       target = arguments[0] || {}, i = 1,   
length = arguments.length, deep = false;
    // Handle a deep copy situation
    if ( typeof target === "boolean" ) {
       deep = target;
       target = arguments[1] || {};
       // skip the boolean and the target
       i = 2;
    }
    // Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
       target = {};
    }
    // extend jQuery itself if only one argument is passed
    if ( length === i ) {
       target = this;//如果参数只有一个,target就指向this
       --i;
    }
    for ( ; i < length; i++ ) {
       // Only deal with non-null/undefined values
       if ( (options = arguments[ i ]) != null ) {
           // Extend the base object
           for ( name in options ) {//开始复制
              src = target[ name ];
              copy = options[ name ];
              // Prevent never-ending loop
              if ( target === copy ) {
                  continue;
              }
              // Recurse if we're merging plain objects or arrays
              if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                  if ( copyIsArray ) {
                     copyIsArray = false;
                     clone = src && jQuery.isArray(src) ? src : [];
                  } else {
                     clone = src && jQuery.isPlainObject(src) ? src : {};
                  }
                  // Never move original objects, clone them
                  target[ name ] = jQuery.extend( deep, clone, copy );
              // Don't bring in undefined values
              } else if ( copy !== undefined ) {
                  target[ name ] = copy;
              }
           }
       }
    }
    // Return the modified object
    return target;
};

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

分享到:
评论
1 楼 快餐盒 2013-09-29  

相关推荐

    Ajax(Jquery与ExtJs)

    Ajax(Jquery与ExtJs) 框架对比 web前端开发

    HTML、JS、ExtJS、jQuery智能提示Eclipse插件

    与ExtJS插件类似,Eclipse的jQuery插件增强了JavaScript编辑器,使开发者在编写jQuery代码时能获得智能提示,比如`eclipse-spket1.6.23_pojie.zip`。 5. **GEF (Graphical Editor Framework)**:`GEF-ALL-3.8.2.zip...

    JavaScript框架jQuery和ExtJS的对比研究.pdf

    "JavaScript框架jQuery和ExtJS的对比研究" 本文将对JavaScript框架jQuery和ExtJS进行对比研究,旨在帮助Web开发者选择合适的JavaScript框架。 JavaScript框架的重要性 随着Web 2.0时代的到来,Web应用程序越来越...

    Extjs,Jquery,Dhtmlxtree之上的树

    ### Extjs、Jquery、Dhtmlxtree之上树的区别及方法变更详解 #### 一、概述 本篇文章主要探讨了三种流行的JavaScript库——Extjs、Jquery、Dhtmlxtree中实现树形结构(Tree)的方法及其差异。树形结构在用户界面...

    ExtJS,JQuery教学支持管理系统

    "ExtJS,JQuery教学支持管理系统"是一个以网页技术为核心的教育管理平台,旨在提供高效、便捷的教学辅助服务。这个系统利用了ExtJS和JQuery这两款强大的JavaScript库,以实现丰富的用户界面和流畅的交互体验。AJAX...

    浅谈JavaScript 库———jQuery, ExtJs 的对比研究

    ### 浅谈JavaScript库——jQuery与ExtJs的对比研究 #### 一、引言 随着Web 2.0和RIA(Rich Internet Applications)技术的普及,JavaScript作为一种前端开发的重要工具,逐渐占据了重要的地位。它不再仅仅是用于...

    仿Extjs的jQuery easyUI

    jQuery EasyUI 是一个基于 jQuery 的轻量级框架,它提供了丰富的用户界面组件,设计灵感来源于 ExtJS。EasyUI 的目标是让开发者能够更快速、更简单地构建具有专业外观和功能的 Web 应用程序。这个框架包含了诸如窗口...

    模仿extjs风格写的jquery combobox

    标题中的“模仿extjs风格写的jquery combobox”指的是一个基于jQuery的下拉选择框组件,它的设计灵感来源于ExtJS库的ComboBox控件。ExtJS是一款功能丰富的JavaScript框架,以其强大的组件化和数据绑定机制著名,而...

    jQuery EasyUI仿Extjs界面

    尽管两者在定位上有所不同,jQuery EasyUI 通过其简洁的API和较低的学习曲线,为开发者提供了一种仿制ExtJS界面效果的方式。 在"jQuery EasyUI 仿 Extjs 界面布局"中,主要涉及以下知识点: 1. **布局管理**:...

    浅谈JavaScript库——jQuery,ExtJs的对比研究.pdf

    "浅谈JavaScript库——jQuery,ExtJs的对比研究.pdf" 本文简要介绍了目前流行的JavaScript库,并对其中较为流行的两个库jQuery和ExtJs进行了较详细的介绍和对比研究。本文首先简要介绍了JavaScript库的概念和特点,...

    Jquery-Extjs4.0框架

    **jQuery与Ext JS 4.0框架详解** jQuery和Ext JS是两种广泛应用于前端开发的JavaScript框架,它们各自有着独特的特性和优势。本篇将详细探讨这两个框架在Jquery-Extjs4.0中的结合使用及其核心概念。 **jQuery框架*...

    extjs使用说明 extjs的API jQuery使用说明 jQuery的API

    ExtJS和jQuery是两种广泛使用的JavaScript库,...然而,随着技术的发展,现代Web开发趋势更多地转向React、Vue和Angular等现代框架,但ExtJS和jQuery仍然是JavaScript历史上的重要里程碑,值得开发者深入理解和学习。

    四种时兴的框架jQuery,Mootools,Dojo,ExtJS的对比

    四种时兴的框架jQuery,Mootools,Dojo,ExtJS的对比

    包括Extjs和jquery做的tree结构

    总结起来,`ExtJS`和`jQuery`都提供了创建`tree`结构的方法,它们在实现上有所不同,但都能满足不同场景的需求。开发者可以根据项目需求,选择适合的工具和方法来构建树形视图。通过学习和实践这些技术,可以提升在...

    四种流行的AJAX框架jQuery_Mootools_Dojo_ExtJS的对比

    ### 四种流行的AJAX框架对比分析:jQuery, Mootools, Dojo, ExtJS #### 一、jQuery **主页**: &lt;http://jquery.com/&gt; **设计思想**: - **简洁性**: 几乎所有操作都始于选择DOM元素,并对其进行操作(支持Chaining...

    2000多个extjs小图标适合jquery EasyUI

    在描述中提到,“2000多个extjs小图标,适合适合jquery EasyUI”,这表明这些图标设计与EXTJS和jQuery EasyUI的风格兼容,能够无缝集成到使用这两种技术的项目中。开发者可以利用这些图标来表示不同的功能、状态或...

    导入extjs、jquery 文件时$使用冲突问题解决方法

    开发者在不注意的情况下使用$时,实际上是引用了jQuery的方法,这可能会破坏ExtJS中基于$的实现。 冲突通常发生在两个库都需要使用$符号进行操作时,它们各自的$方法可能会相互覆盖,造成某些功能无法使用或出现...

    spket extjs jquery

    综上所述,这个压缩包提供的资源涵盖了前端开发的重要组成部分,包括强大的开发环境Spket、Java EE IDE MyEclipse的扩展、富客户端框架ExtJS、强大的JavaScript库jQuery及其表单处理插件,以及用于构建用户界面的...

    extjs实用开发指南.rar

    extjs extjs技术 extjs框架 extjs与jquery extjs

    Ajax+extjs+jquery+javascript必备开发帮助文档

    通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这使得网页应用程序能够更加迅速地响应用户操作,提高了用户体验。主要知识点包括: 1. XMLHttpRequest 对象:Ajax 的核心,用于在后台与服务器...

Global site tag (gtag.js) - Google Analytics