1. 问题描述:
Ext文件异步加载、解释、执行的问题。因为这里涉及了EXT面向对象,所以需要对EXT类的定义有深入的理解(本文略)。
2. 一个简单的异步加载思路
/** * 定义需要加载的模块的文件路径 */ loadUserModule = function (callback) { var js = ["/paims/users/User.js"]; js[js.length] = "/paims/users/UserStore.js"; js[js.length] = "/paims/users/UserXmlReader.js"; js[js.length] = "/paims/users/UserGridPanel.js"; js[js.length] = "/paims/users/UserGridPanel_ColumnModel.js"; loadJs(js, '用户模块', function () { // 调用异步加载方法,加载文件 callback(); }); }
/** * 异步加载JS文件 */ loadJs = function (jsPath,moduleName,callback) { if (Ext.type(js) != 'string') { if (js.length == 1) { js = js[0]; } else { js = js.shift(); callback = loadJs; } } Ext.Ajax.request({ url: '/javascript' + js, success: onLoadJs, method: 'GET', scope: callback }); }
/** * 文件加载完成之后,解释执行 */ onLoadJs = function (response) { eval(response.responseText); // 解释执行JS文件内容,忽略eval的副作用 this(); // 执行回调 }
3. 运行效果如下:
注意:这里的文件是顺序加载的,原因是在执行递归方法的时候,有一个时间消耗,大概是50ms,导致任意两次Ajax请求直接的时间间隔至少是50ms。
4.UserStore和UserXmlReader两个文件的内容如下:
Paims.users.UserStore = Ext.extend(Paims.data.XmlStore, { constructor: function(load_url, params){ Paims.users.UserStore.superclass.constructor.call(this, new Paims.users.UserXmlReader(), load_url, params); } });
Paims.users.UserXmlReader = Ext.extend(Paims.data.XmlReader, { constructor: function(){ Paims.users.UserXmlReader.superclass.constructor.call(this, Paims.users.User); } });
观察UserStore的源码可以发现,在UserStore中用到了UserXmlReader类。第一直觉,会认为这里在解释执行UserStore文件的时候会报异常,以为在解释执行UserStore的时候UserXmlReader还没有被加载。事实上,却一切正常。因为,UserStore对UserXmlReader的依赖关系写到了constructor方法里,而方法只进行了解释,没有被执行。
5.深入体会Ext类的定义和执行
修改UserStore类的定义如下:
Paims.users.UserStore = Ext.extend(Paims.data.XmlStore, { constructor: function(load_url, params){ Paims.users.UserStore.superclass.constructor.call(this, new ABC(), load_url, params); } });
UserStore中依赖了一个毫无相关的ABC类(方法)。
加载UserStore文件,并解释执行,一切正常,如下图:
只有当UserStore被实例化,执行constructor方法的时候,才会报错,如下图:
这里可以这样理解,在加载文件并解释执行的时候,只是解释执行了最外层方法的内容。如果没有显示的执行调用的话,内层的方法是不会执行了。
比如,上例中解释执行的时候,只是执行了最外层的Ext.extend()方法,内层的constructor方法并不会被执行,所以new ABC()语句也不会被执行(但会被解释)。
6. 对于解释执行的理解:
修改UserStore类的定义如下:
Paims.users.UserStore = Ext.extend(Paims.data.XmlStore, { constructor: function(load_url, params){ Paims.users.UserStore.superclass.constructor.call(this, new ABC(), load_url, params); } }); new ABC(); // 注意
这次,当解释执行UserStore文件的时候会报错,如下图:
因为位于最外层的new ABC();被解释执行了。
7. 两个小例子
解释执行最外层
执行内层方法name()
解释执行最外层
执行方法fn()
总结:虽然JS是边解释边执行,但是没有被显示调用的方法只会被解释,不会被执行,只会被检查编译时错误(语法),不会被检查运行时错误。