zoukankan      html  css  js  c++  java
  • ExtJs 源码笔记------Ext.js

    ExtJs 源码笔记------Ext.js

    最近准备系统的学习一下Ext的源码,SO,话不多说,从第一篇开始。

    首先,先看一下Ext.js这个文件的代码结构:

    var Ext = Ext || {}; // 定义全局变量
    Ext._startTime = new Date().getTime();
    
    (function(){
         
         // 定义一些局部变量
         var ......
    
         // 核心
         Ext.apply = function(){......};
    
        // 初始化 Ext 的一些属性函数
        Ext.apply(Ext, {......});
        
    }());
    
    // 全局闭包
    Ext.globalEval  = ......

    代码的结构不难,但是仔细看下来,有些细节的地方还是很值得回味一番。下面具体分析一下我对源码的理解,水平有限,不足之处还望各位看官指正。

    1. 定义局部变量

      var global = this,
            objectPrototype = Object.prototype,
            toString = objectPrototype.toString,
            enumerables = true,
            enumerablesTest = {toString: 1},
            emptyFn = function () {},
            ......
    
        for (i in enumerablesTest) {
            enumerables = null;
        }
    // 看到这里的时候,有点疑惑,enumerables 不是肯定会被置为 null 吗 // 下面为什么还需要判断enunerables? 有蹊跷..... // 返回去再看一下 enumerablesTest,里面只有一个属性 toString, 为啥偏偏是这样的一个属性?? 嗯!想起来了,在IE6下,对象中的toString属性,不能通过
    hasOwnProperty或for...in迭代得到
    // So,这里其实就是为了兼容IE6用的。bingo! if (enumerables) { enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; }

    2.Ext.apply

    Ext.apply = function(object, config, defaults) {
            if (defaults) {
                Ext.apply(object, defaults);
            }
    
            if (object && config && typeof config === 'object') {
                var i, j, k;
                
                // 拷贝对象,不过这里只是实现了浅拷贝,即如果一个对象中的属性也是一个Object或者Array,会有引用的问题。
                for (i in config) {
                    object[i] = config[i];
                }
              
                // 兼容IE6
                if (enumerables) {
                    for (j = enumerables.length; j--;) {
                        k = enumerables[j];
                        if (config.hasOwnProperty(k)) {
                            object[k] = config[k];
                        }
                    }
                }
            }
    
            return object;
        };
        

    Ext.apply没有实现深层拷贝对象的功能,要想了解更多的关于Ext中拷贝对象的内容,可以狠狠的点击这里

    3.初始化 Ext 对象

    3.1

    Ext.apply(Ext, {
    
           ......
            // 拷贝对象,不去覆盖object中的原始属性。
            applyIf: function(object, config) {
                var property;
    
                if (object) {
                    for (property in config) {
                        if (object[property] === undefined) {
                            object[property] = config[property];
                        }
                    }
                }
    
                return object;
            },
    
            // array 和 object 的数据迭代
            iterate: function(object, fn, scope) {
                if (Ext.isEmpty(object)) {
                    return;
                }
    
                if (scope === undefined) {
                    scope = object;
                }
    
                // 可以看到这里真正起作用的是 Ext.Array.each 和 Ext.Object.each方法。
    
                if (Ext.isIterable(object)) {
                    Ext.Array.each.call(Ext.Array, object, fn, scope);
                }
                else {
                    Ext.Object.each.call(Ext.Object, object, fn, scope);
                }
                // 复习一下 function.call的用法,第一个参数指定的函数运行过程中所指代的 this。
            }
        });

    3.2

     Ext.apply(Ext, {
    
            // 在4.0或以上版本中这个方法已经被Ext.define取代
            extend: ......
        
            override: function (target, overrides) {
                if (target.$isClass) {
                    // 若target是一个 class,则调用该类自己的override方法
                    target.override(overrides);
                } else if (typeof target == 'function') {
                     // 若target是一个 function, 则将overrides拷贝到原型链上
                    Ext.apply(target.prototype, overrides);
                } else {   
                    // 若是一个类的实例, 最后需要调用一下 callParent() 方法
                    /**     
                    *      var panel = new Ext.Panel({ ... });
                    *      Ext.override(panel, {
                    *          initComponent: function () {
                    *              // extra processing...
                    *
                    *              this.callParent();
                    *          }
                    *      });
                    */
                    var owner = target.self,
                        name, value;
    
                    if (owner && owner.$isClass) {
               
                        for (name in overrides) {
                            if (overrides.hasOwnProperty(name)) {
                                value = overrides[name];
    
                                if (typeof value == 'function') {
                                    //<debug>
                                    if (owner.$className) {
                                        value.displayName = owner.$className + '#' + name;
                                    }
                                    //</debug>
    
                                    value.$name = name;
                                    value.$owner = owner;
                                    value.$previous = target.hasOwnProperty(name)
                                        ? target[name] // already hooked, so call previous hook
                                        : callOverrideParent; // calls by name on prototype
                                }
    
                                target[name] = value;
                            }
                        }
                    } else {
                        // 若target只是一个普通对象,则调用apply方法即可。
                        Ext.apply(target, overrides);
                    }
                }
    
                return target;
            }
        });                                   

    3.3 初始化一些类型验证函数,这里只记录了两个不常见的,剩下的也比较简单

     Ext.apply(Ext, {
    
           ......
    
           // 判断是否是 HTMLElement
            isElement: function(value) {
                return value ? value.nodeType === 1 : false;
            },
     
           // 判断是否是TextNode      
            isTextNode: function(value) {
                return value ? value.nodeName === "#text" : false;
            },
    
           ...... 
        });

    3.4

     Ext.apply(Ext, {
    
             // 复制对象,包括 [], {}, dom, date. 不会产生引用对象。
            clone: function(item) {
                var type,
                    i,
                    j,
                    k,
                    clone,
                    key;
                
                if (item === null || item === undefined) {
                    return item;
                }
    
                // DOM nodes
                if (item.nodeType && item.cloneNode) {
                    return item.cloneNode(true);
                }
    
                type = toString.call(item);
    
                // Date
                if (type === '[object Date]') {
                    return new Date(item.getTime());
                }
    
    
                // Array
                if (type === '[object Array]') {
                    i = item.length;
    
                    clone = [];
    
                    while (i--) {
                        clone[i] = Ext.clone(item[i]);
                    }
                }
                // Object
                else if (type === '[object Object]' && item.constructor === Object) {
                    clone = {};
    
                    for (key in item) {
                        clone[key] = Ext.clone(item[key]);
                    }
    
                    if (enumerables) {
                        for (j = enumerables.length; j--;) {
                            k = enumerables[j];
                            if (item.hasOwnProperty(k)) {
                                clone[k] = item[k];
                            }
                        }
                    }
                }
    
                return clone || item;
            },
    
            ......
    
    });

    4. Ext.globalEval

    Ext.globalEval = Ext.global.execScript
        ? function(code) {
            // exexScript作用域是全局闭包
            execScript(code);
        }
        : function($$code) {
            (function(){
                // 这里需要让 Ext 指代的是全局变量的Ext对象
                var Ext = this.Ext;
                eval($$code);
            }());
        };

    这里还需要多说两句的是 eval & window.eval & window.execScript 的区别

    首先 eval 和 window.eval 的区别,可以参考这篇文章。简单点说,就是eval是局部闭包,而window.eval是全局闭包

    window.execScript只有IE认识,且也是全局闭包。以后有时间再来详细分析一下三者之间的区别。

    -----------------------------一花开五叶 结果自然成-------------------------------------------------
  • 相关阅读:
    【iOS基础控件 6 】 汽车品牌展示 Model嵌套/KVC/TableView索引 <UITableView>
    RAC
    Magical Data Modelling Framework for JSON
    Xcode插件管理工具Alcatraz
    iOS8 Size Classes的理解与使用
    Storyboard、xib中的UIScrollView使用autolayout,使其能够滚动
    iOS事件响应链
    git一些常用的操作(转载)
    iOS本地数据存储(转载)
    使用react-native做一个简单的应用-04界面主框架
  • 原文地址:https://www.cnblogs.com/zyc-undefined/p/3244796.html
Copyright © 2011-2022 走看看