Extjs 研究 Ext.extend

  1. /*   
  2. * Ext JS Library 2.0   
  3. * Copyright(c) 2006-2007, Ext JS, LLC.   
  4. * licensing@extjs.com   
  5.  
  6. * http://extjs.com/license   
  7. */    
  8. //构建Ext单例对象    
  9. //js中可以直接创建对象,这和java、c++等OO语言中    
  10. //只能定义类,再创建对象是不一样的了    
  11. //这种方式是js中构建单例对象的一个比较好的方式了    
  12. Ext = {version: '2.0' };   
  13.   
  14. //在浏览器端开发中,window是全局对象    
  15. //下面句子往window这个全局对象中动态注入undefined属性    
  16. //尽管在emac的标准中要求全局对象中必须有个undefined的状态    
  17. //但是当浏览器替换了全局对象时间,undefined这个变量的状态可能    
  18. //就定义了。特别是old browsers....这样的解释有任何问题可以一起留言商讨    
  19. //这样的处理方式只能针对undefined的了。    
  20. // for old browsers    
  21. window["undefined" ] = window[ "undefined" ];   
  22. /**   
  23. * @class Ext   
  24. * Ext core utilities and functions.   
  25. * @singleton   
  26. */    
  27. /**   
  28. * Copies all the properties of config to obj.   
  29. * @param {Object} obj The receiver of the properties   
  30. * @param {Object} config The source of the properties   
  31. * @param {Object} defaults A different object that will also be applied for default values   
  32. * @return {Object} returns obj   
  33. * @member Ext apply   
  34. */    
  35. Ext.apply = function (o, c, defaults){  //从代码的实现过程来看defaults中的属性会被c中属性覆盖,default只有在    
  36.                                        //c中没有定义的时候,才会用default中定义的属性    
  37.     if (defaults){   
  38.       
  39.         //显然这里用this也是可以调用到Ext中的apply方法的,但是想想为什么这里不用this呢?就是说下面的句子直接改为    
  40.         //this.apply(o.defaults)。    
  41.         //下面作者的注释已经说明了问题的所在了。为了在scope(作用域)之外可以友好地调用到该方法,该方法定义    
  42.         //在Ext这个全局的单例的对象之中,那么scope就是指Ext内了。那么在Ext之外调用时什么意思呢?不是可以通过    
  43.         //Ext.apply直接调用到吗,这有什么问题?    
  44.         //这样当然没有问题。不过想想js中函数调用的另外一种方式:Ext.apply.apply或者Ext.apply.call。    
  45.           
  46.         //我想作者指的调用方式,就是call和apply这种scope范围之外的调用方式吧。这样作用域外调用会的话,用this关键字的话    
  47.         //问题就来了。如:function Man(){}   ,Ext.apply.call(new Man(),new Man(),new Woman());    
  48.         //用上“this” reference    
  49.         //会抛出个错误说Man中的apply未定义。    
  50.           
  51.         //apply和call的这种调用方式,都会有this问题。如果是Ext这样的单例对象的话,建议都不要this来内部调用,都搞Ext前缀算了。    
  52.         //以免引发一些“friendly”的问题。    
  53.        
  54.         // no "this" reference for friendly out of scope calls    
  55.         Ext.apply(o, defaults); //这里要开始递归调用Ext.apply的方法了,如果defaults存在的话,递归第一轮就走到下面的代码去了。    
  56.     }   
  57.       
  58.     //这里o&&c都还好理解,说明只要在o和c都存在的时候才有必要做某些操作,那么typeof c=='object'又是为了限制什么呢    
  59.     //如果不加上这个条件会怎么样?    
  60.     //这个问题与typeof能区分出什么东西息息相关,从犀牛中的typeof的解释上看,typeof只能区分对象类型与基本类型。    
  61.     //也就是说,如果发现c是基本类型的话,下面的属性拷贝工作就根本不会做了(也不应该做,但是如果真得传递一个1进去,好像也不会出现啥恐怖的事情)。    
  62.       
  63.     if (o && c &&  typeof  c ==  'object' ){   
  64.       
  65.      //这个就没啥好说的,c中的属性被全部拷贝到o中了    
  66.         for ( var  p  in  c){   
  67.             o[p] = c[p];   
  68.         }   
  69.     }   
  70.       
  71.     return  o;   
  72. };   
  73.   
  74.   
  75. //这里使用匿名函数来完成Ext这个单例对象中相关属性的设置    
  76. //形如:(function(){})();    
  77. //那么这里使用匿名函数是否是有什么特殊的考虑?    
  78. //尽管这个匿名函数的逻辑可以定义在某个有名的函数,如init_ext()中,然后再加以调用    
  79. //但是能用匿名函数一步到位的事情为啥要分两个步骤呢:)    
  80. //充分利用语言的性质,看来使用匿名函数形成的闭包来做初始化工作也是不错的了。    
  81. (function (){   
  82.     var  idSeed = 0;  //查看下面的Ext.id方法,用来对id递增    
  83.       
  84.       
  85.     //下面这些策略就是为了判断浏览器的类型了,很常见的一种用法    
  86.     //既然Ext是一个cross-browser的框架,那么肯定要知道自己运行的平台是哪种浏览器了... ...    
  87.     var  ua = navigator.userAgent.toLowerCase();   
  88.     //下面是摘自dhtml网页制作完全手册中,对document.caompatMode的描述    
  89.    When standards-compliant mode is switched on, Internet Explorer renders the document in compliance with the Cascading Style Sheets (CSS), Level 1 (CSS1)  standard. When standards-compliant mode is not switched on,    
  90.    // rendering behavior is consistent with previous versions of Internet Explorer.    
  91.     var  isStrict = document.compatMode ==  "CSS1Compat" ,    
  92.         isOpera = ua.indexOf("opera" ) > -1,   
  93.         isSafari = (/webkit|khtml/).test(ua),   
  94.         isIE = !isOpera && ua.indexOf("msie" ) > -1,   
  95.         isIE7 = !isOpera && ua.indexOf("msie 7" ) > -1,   
  96.         isGecko = !isSafari && ua.indexOf("gecko" ) > -1,   
  97.         isBorderBox = isIE && !isStrict,   
  98.         isWindows = (ua.indexOf("windows" ) != -1 || ua.indexOf( "win32" ) != -1),   
  99.         isMac = (ua.indexOf("macintosh" ) != -1 || ua.indexOf( "mac os x" ) != -1),   
  100.         isLinux = (ua.indexOf("linux" ) != -1),   
  101.         isSecure = window.location.href.toLowerCase().indexOf("https" ) === 0;   
  102.   
  103.      //就是说ie7之前的ie浏览器对背景图像有些默认的处理方式,按作者的注释说,如果不执行这个command的话    
  104.      //css 图片会晃动。    
  105.     // remove css image flicker    
  106. if (isIE && !isIE7){   
  107.         try {   
  108.             document.execCommand("BackgroundImageCache"falsetrue );   
  109.         }catch (e){}   
  110.     }   
  111.   
  112.     //来了,在这里将往Ext这个大对象中加入属性了    
  113.     Ext.apply(Ext, {   
  114.         /**   
  115.          * True if the browser is in strict mode   
  116.          * @type Boolean   
  117.          */    
  118.         isStrict : isStrict,  //函数开始位置对平台检测的结果用上了...    
  119.         /**   
  120.          * True if the page is running over SSL   
  121.          * @type Boolean   
  122.          */    
  123.         isSecure : isSecure,   
  124.         /**   
  125.          * True when the document is fully initialized and ready for action   
  126.          * @type Boolean   
  127.          */    
  128.         isReady : false ,   
  129.         /**   
  130.          * True to automatically uncache orphaned Ext.Elements periodically (defaults to true)   
  131.          * @type Boolean   
  132.          */    
  133.         enableGarbageCollector : true ,   //注意看下面的Ext的垃圾回收算法... ...    
  134.         /**   
  135.          * True to automatically purge event listeners after uncaching an element (defaults to false).   
  136.          * Note: this only happens if enableGarbageCollector is true.   
  137.          * @type Boolean   
  138.          */    
  139.         enableListenerCollection:false ,    //注意Ext中对缓存机制....在缓存元素被删除之后,元素上面的监听器(元素上面可能绑定很多类似事件的监听器)一并会被删除掉    
  140.   
  141.         /**   
  142.          * URL to a blank file used by Ext when in secure mode for iframe src and onReady src to prevent   
  143.          * the IE insecure content warning (defaults to javascript:false).   
  144.          * @type String   
  145.          */    
  146.         SSL_SECURE_URL : "javascript:false"//这个用在啥地方,很用途还不是很清楚    
  147.         /**   
  148.          * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images. (Defaults to   
  149.          * "http://extjs.com/s.gif" and you should change this to a URL on your server).   
  150.          * @type String   
  151.          */    
  152.         BLANK_IMAGE_URL : "http:/" + "/extjs.com/s.gif"//空白css背景图片,这个一定要该,否则在内存上部了网的时候,可能会出现图标正在下载的情况//下不到的话,则可能会有叉叉    
  153.         /**   
  154.         * A reusable empty function   
  155.         * @property   
  156.          * @type Function   
  157.         */    
  158.         emptyFn : function (){},   //一个占位符函数,就是用了指导某个函数上... ...prototype框架里面也专门定义了个 空函数 属性    
  159.         /**   
  160.          * Copies all the properties of config to obj if they don't already exist.   
  161.          * @param {Object} obj The receiver of the properties   
  162.          * @param {Object} config The source of the properties   
  163.          * @return {Object} returns obj   
  164.          */    
  165.         applyIf : function (o, c){  //注意与Ext.apply方法的区别,该方法只有在属性没有定义的时候才会拷贝c中的属性    
  166.             if (o && c){   
  167.                 for ( var  p  in  c){    //回忆下undefined状态,undefined状态意味着对象属性没有定义,或者某个对象声明却没有赋值    
  168.                     if ( typeof  o[p] ==  "undefined" ){ o[p] = c[p]; }   
  169.                 }   
  170.             }   
  171.             return  o;   
  172.         },   
  173.         /**   
  174.          * Applies event listeners to elements by selectors when the document is ready.   
  175.          * The event name is specified with an @ suffix.   
  176. <pre><code>   
  177. Ext.addBehaviors({   
  178.    // add a listener for click on all anchors in element with id foo   
  179.    '#foo a@click' : function(e, t){   
  180.        // do something   
  181.    },   
  182.    // add the same listener to multiple selectors (separated by comma BEFORE the @)   
  183.    '#foo a, #bar span.some-class@mouseover' : function(){   
  184.        // do something   
  185.    }   
  186. });   
  187. </code></pre>   
  188.          * @param {Object} obj The list of behaviors to apply   
  189.          */    
  190.            
  191.         addBehaviors : function (o){   //似乎是因为使用上DomQuery库,在Ext中似乎有许多地方都使用 css的 selector(选择器)来定位一个dom节点    
  192.             if (!Ext.isReady){         //想想使用css定位器来定位对象,看来也挺ok的,元素都定位得到了。    
  193.                 Ext.onReady(function (){   
  194.                     Ext.addBehaviors(o);   
  195.                 });   
  196.                 return ;   
  197.             }   
  198.               
  199.             //这个cache只是用来,做为算法的辅助工具    
  200.             //Ext.select毕竟是耗时间的事情,能省则省啊,而且一般情况下,我们调用一次addBehaviors方法只对一个元素增加监听器会比较清楚些。    
  201.               var  cache = {};  // simple cache for applying multiple behaviors to same selector does query multiple times    
  202.             for ( var  b  in  o){   
  203.                 var  parts = b.split( '@' );   
  204.                 if (parts[1]){  // for Object prototype breakers    
  205.                     var  s = parts[0];   
  206.                     if (!cache[s]){   
  207.                         cache[s] = Ext.select(s);   
  208.                     }   
  209.                     cache[s].on(parts[1], o[b]);  //Element的on方法了    
  210.                 }   
  211.             }   
  212.             cache = null ;   
  213.         },   
  214.   
  215.          
  216.         /**   
  217.          * Generates unique ids. If the element already has an id, it is unchanged   
  218.          * @param {Mixed} el (optional) The element to generate an id for   
  219.          * @param {String} prefix (optional) Id prefix (defaults "ext-gen")   
  220.          * @return {String} The generated Id.   
  221.          */    
  222.         id : function (el, prefix){  //产生一个唯一的ID    
  223.             prefix = prefix || "ext-gen" ;   
  224.             el = Ext.getDom(el);   
  225.             var  id = prefix + (++idSeed);   
  226.               
  227.             //由于js支持类型转化,所以对象本身可以直接成为条件运算的内容,el是否存在在js中直接用if(el)来判断。    
  228.             return  el ? (el.id ? el.id : (el.id = id)) : id;  //el没id则才弄出id;这个要是弄好点的话,可以在函数的最开始做判断,这样就有可能免掉Ext.getDom(e1)这样的运算了。    
  229.         },   
  230.         /**   
  231.          * Extends one class with another class and optionally overrides members with the passed literal. This class   
  232.          * also adds the function "override()" to the class that can be used to override   
  233.          * members on an instance.   
  234.          * @param {Object} subclass The class inheriting the functionality   
  235.          * @param {Object} superclass The class being extended   
  236.          * @param {Object} overrides (optional) A literal with members   
  237.          * @method extend   
  238.          */    
  239.         extend : function (){   
  240.               
  241.             //extend是重要的函数了,OO的继承在Ext中靠它了    
  242.             //语法上使用上了个闭包    
  243.             //函数定义完之后,马上进行调用,并且返回了也是个函数    
  244.               
  245.               
  246.             //从该函数的实现上看,该函数值针对子类以及父类的prototype操作,难怪Ext要求要在子类的构造函数中进行这样的调用语句    
  247.             //Subclass.superclass.constructor.call(this,arguments);显示地拷贝父类中非prototype定义的属性    
  248.             //如果非prototype所定义的方法,将不会被overrides中的属性所覆盖.    
  249.           
  250.           
  251.             // inline overrides    
  252.             var  io =  function (o){   
  253.                 for ( var  m  in  o){   
  254.                     this [m] = o[m];   
  255.                 }   
  256.             };   
  257.               
  258.               
  259.             return   function (sb, sp, overrides){   
  260.               
  261.                 /**   
  262.                   (转)   
  263.                 1,关于F的用法   
  264.                   使用F是为了避免对sb原型对象的操作,联动影响sp的原型对象.   
  265.                 2,当typeof sp == "function"时   
  266.                 sb的原型将被替换,不保留任何原型属性   
  267.                 sb的superclass指向sp的原型对象   
  268.                   
  269.                3,当typeof sp == "object"时   
  270.                 sb的原型属性将被保留   
  271.                 sb的superclass指向自己的原型对象   
  272.                   效果略等同于override   
  273.                   另:   
  274.                 1,apply,applyIf主要用于typeof == "object"时的对象操作   
  275.                 2,override,extend主要用于typeof == "function"时的对象原型操作   
  276.                           
  277.                 **/    
  278.               
  279.               
  280.               
  281.                  
  282.                 if ( typeof  sp ==  'object' ){  //如果sp也是对象的话,而不是函数类 (!='function').一般来说sp这里放的是父类的构造函数),那么第三个参数overrides参数相当于被忽略掉    
  283.                     overrides = sp;   
  284.                     sp = sb;   //sb重新定义了函数    
  285.                 }   
  286.                   
  287.                   
  288.                   
  289.                  
  290.                 var  F =  function (){}, sbp, spp = sp.prototype;   
  291.                 F.prototype = spp;   
  292.                 sbp = sb.prototype = new  F();   
  293.                 sbp.constructor=sb;   
  294.                   
  295.                              
  296.                 sb.superclass=spp;   
  297.                   
  298.                 if (spp.constructor == Object.prototype.constructor){   
  299.                     spp.constructor=sp;   
  300.                 }   
  301.                 sb.override = function (o){   
  302.                     Ext.override(sb, o);   
  303.                 };   
  304.                 sbp.override = io;   
  305.                   
  306.                 //覆盖掉子类prototype中的属性    
  307.                 Ext.override(sb, overrides);   
  308.                 return  sb;   
  309.             };   
  310.         }(),   
  311.   
  312. 关于两个参数与三个参数extend方法注释补充。   
  313.       
  314.    /**   
  315.          Ext.extend的两个参数的与三个参数的使用方法很不一样。   
  316.           三个参数如:   
  317.          Ext.extend(Sub,Super,{})   
  318.            
  319.           直接改变了Sub的构造函数本身,让Sub的prototype指向   
  320.          Super。   
  321.           
  322.           两个参数如:   
  323.          Ext.extend(Sub,{});   
  324.           并不改变Sub本身,从代码中看由于传递进去的Sub引用(引用的拷贝)被   
  325.           替换为新的function,而Sub本身却没有被改变,所以   
  326.          Ext.extend(Sub,{});的执行不会改变Sub本身。   
  327.            
  328.           两个参数的extend的使用时通过,接收其返回才有意义:   
  329.             
  330.          OSub = Ext.extend(Sub,{});   
  331.            
  332.          Ext中也有许多地方用到两个参数的extend,如:   
  333.            
  334.          Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {   
  335.       
  336.          readRecords : function(o)   
  337.          {   
  338.           
  339.          // do something   
  340.            
  341.          }   
  342.         });                 
  343.            
  344.          */  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值