`
eueuy
  • 浏览: 70516 次
  • 性别: Icon_minigender_1
  • 来自: 天津
最近访客 更多访客>>
社区版块
存档分类
最新评论

JavaScript中的对象动态加载技术

阅读更多

什么是JavaScript对象动态加载

JavaScript动态加载(JavaScript Object Dynamic Loading) - 之所以叫做动态,是应为其有别与通常的静态加载形式。

典型的JavaScript静态加载方式,是通过<script>标签将我们可能需要的所有JS文件依次嵌入到一个HTML页面中,当浏览器执行到<script> 标签,就会到我们指定的地方去加载JavaScript并运行,这时,文件中定义的无论方法、类、对象等,已经存在与浏览器,等待被使用。除非HTML页面被Unload,否则这些东西就一直存在。

而典型的动态加载方式,是不需要任何提前的准备,只有当需要一个JavaScript对象来为我们服务时,我们就临时去加载它所属的JS文件,然后使用它,使用完毕,销毁即可。正所谓“呼之即来,挥之即去”。

就因为这“呼之即来,挥之即去”的能力,使得JavaScript真正的活了起来。

 

JS动态加载解决了什么问题

  1. 给系统减了肥:可以将不必要的JavaScript代码延迟加载,未用到的功能不加载。
  2. 模块化得以实现:可以将原本大块的功能或类,分解成合理的小块,便于管理与维护。
  3. 方便的值传递:双向传值,无拘束。基于JSON,可以传递大对象。
  4. 可以实现Service:可以基于Service理念,通过核心JavaScript对象使用其他的服务功能对象,完成业务的组装。

JS动态加载应该有什么能力

  1. 可以异步的,或同步的,随心所遇加载外部JS文件。
  2. 加载进来的JS文件的内容可以有效管理,包括作用域,开放性,生命周期。
  3. 可以支持面向对象,以对象为基本点而不是方法或变量等。
  4. 有好的封装,可以通过一个句柄操作整个被加载的JS。

传统JS动态加载的实现

关于JS动态加载的实现,我见过很多种方法。早期的时候,人们想过很多办法。这些办法有自己发挥的空间,可以解决一些问题。但是都或多或少的存在弊端,以及实现上的繁琐,最大的问题就是,它们基本都不是面向对象的。下面就列举主要的2类:

  1. 用嵌套iFrame的方式来加载JS文件:这种方式早期最多,通过在页面中包含一个iFrame,来调用一个另一个包含了<script>标签的HTML页面,实现JS的动态加载。最大的弊端就是无法传递参数,实现较繁琐。
  2. 临时创建<script>标签:这种方式有很多人用。利用JavaScript操作页面Dom模型,临时创建一个<script>标签,然后appendChild到<body>上,或者动态改变已存在<scirpt>标签的src属性。弊端是只能同步加载,必须等待JS文件被读取完毕,才能进行下一步工作。且传值是通过调用被加载的JS内的变量实现,双向传值困难,作用域弱化。

可以看出以上两种常见方式,都无法满足我们的要求。

更优秀的解决方案

得益于神奇如阿拉丁神灯般的 eval() ,我们就可以实现以上所有的愿望 :) 。

绕了那么大圈子,想了那么多办法。其实最简单的方法就在眼皮底下.

第一部分-调用方 main.js文件:

//动态读取JS对象的方法

//@FileName:要读取的JS对象URL,可以是本地路径。

//@TheParameters:需要传递给被加载对象的参数,可以是任何对象。

function loadJSObj(FileName,TheParameters){
    Ext.Ajax.request({   //异步调用方法
        url: FileName,   //调用URL
        scope: this,  
        success: function(response){   //成功后的回调方法response为返回内容
            var remoteObj = eval(response.responseText);
            var mod = null;
            mod = new remoteObj(TheParameters);

            return mod;
        },
        failure:function(){   //失败后的回调方法
            alert(name+' - 读取失败,请检查网络或文件。');

            return null;
        }
    });
}

这段代码使用Extjs类库封装的异步读取方法Ext.Ajax.request()。只是为了方便。如果你使用未封装的XMLHttpRequest对象也没什么问题。

先大概说下loadJSObj方法干的事情是:

  1. 用XMLHttpRequest来了一次Ajax请求,将想要加载的JS文件源代码读过来。
  2. 利用eval函数将刚才读到的远程JavaScript类实例化成为本地的对象(期间传递了构造参数)。
  3. 返回这个对象,供使用。

此处关键的代码在于

            var remoteObj = eval(response.responseText);
            var mod = null;
            mod = new remoteObj(TheParameters);

            return mod;

可以看到,我们直接将被读取的JS文件传进eval 函数执行。并返回一个叫做 remoteObj的东西,这个东西其实就是被读取的JS的句柄(一个类,定义在被读取JS中的类,后面会详细说到),通过将remoteObj实例化,即mod = new remoteObj(参数) 就可以通过 mod 对象对被读取的JS随心所欲了操作了。

如此一来,远程的JS就被我们按照参数中指定的要求实例化成本地对象了,可以使用了。但是…这只是一相情愿。因为被读取的JS得符合我们的要求,才能“两厢情愿”,最终得到结果…

第二部分 - 被调用方 login.js文件:

要想符合要求,被读取的JS文件也必须按照一定的规则来写。

//用户登录类

Ext.extend(eueuy.module,{
    init:function(){   
        //==Variables==//
        var userName = this.parameters.un;  //获取传递进来的参数un
        var passWord = this.parameters.pwd;   //获取传递进来的参数pwd 
       
        //==Methods==//
        //登录方法
        function loginOn(){
            if (userName=='eueuy' || passWord=='123'){ 
                return true;               
            }else{
                return false;
            }
        }
        //登出方法       
        function loginOff(){ 
            alert('欢迎再来');

        }
    }
});

我们先看看这个登录类干了什么:

  1. 继承自eueuy.moudle,并重写了构造函数。
  2. 接收了2个传递进来的初始化参数,un 和 pwd。
  3. 定义了2个成员方法和一个成员变量。

没有任何特别的东西,就是Ext.extend方法用的有点怪,区别于平常的 XXX = Ext.extend();

没有赋值符号和类名。这恰恰是一个关键点:

类的名字必须留空

为什么这样写?因为这样一来,这个没有类名的类, 就可以在eval()函数执行他的时候,再给他定义类名,这样就将类名的定义留在了调用的时候,也就是main.js文件中。这个小技巧也将使调用方(main.js)可以直接控制被调用方(login.js)的类。

最后,就可以在main.js中用下面的代码,通过动态加载用户登录类,进行用户登录验证的工作:

var loginModel = loadJSObj('http://www.eueuy.name/project1/js/login.js',{un:’eueuy’,pwd:’123’});

if (loginModel.loginOn()){

    alert('登录成功,欢迎'+loginModel.userName);

}else{

    alert('登录失败,错误的用户名密码');

}

可以看到,在上面的代码中,我们通过loginModel这个变量,控制了login.js中的登录类,可以访问其中的方法loginOn() ,还可以访问其中的变量 userName。

 

结尾

至此,对象动态加载技术的理论已经讲解的差不多了,再下一篇博文中,我还会依据这些理论,给大家贴出一个基于动态加载的的项目框架。这个框架可以方便的实现One-Page,还可以看到一些具体的应用。

分享到:
评论
10 楼 eason007 2010-05-07  
<p>js的动态加载,要处理异步不难。难的是如何并行加载,并且保持顺序,还能不阻塞其他资源的下载。最好还能实现模块化的加载。</p>
<p> </p>
<p>贴点我自己的框架的代码,和yui的有点像。</p>
<pre name="code" class="js">EAS_JS.Script
.build({
name : 'jquery',
url : 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'
})
.build({
name : 'local',
def : function () {
$('#test').html($('#test').html() + 'local &gt; ');
}
})
.build({
name : 'test',
url : 'http://www.w2blog.net/Templates/script/opFeedback.js'
})
.build({
name : 'index',
def : function () {
$('#test').html($('#test').html() + 'index &gt; ');
},
requires : ['jquery', 'local', 'test']
});

EAS_JS.Script.run({
name : 'index'
});</pre>
<p> </p>
9 楼 eason007 2010-05-07  
ajax方式是不能加载跨域文件的。
8 楼 eueuy 2010-05-06  
dzxiang 写道
eueuy 写道
rainsilence 写道
var remoteObj = eval(response.responseText);
var mod = new remoteObj(TheParameters);

突然出现一个类,lz觉得这种方法好吗?
这个方法最早出现在2006年的csdn上,用于图片切换。
主要用途不是为了什么动态加载(lz的动态加载的理解还是有问题。难道你会把不会用到的<script标签加载进来吗?而且lz提出的挥之则去,怎么挥之则去?eval了还想去掉?所以相比script,如果单单只是从动态加载上考虑,可以说没有任何意义),而是为了核心js代码隐藏。但是Lz的这种做法还是太简单了,远远达不到代码隐藏的程度。


将MOD对象释放即可

与我现在的项目中用到的方式基本一样,我想了解一下楼主关于“将MOD对象释放”,是如何做的?


mod = null;
如果愿意还可以调用一下 GC函数 ,不过内存稍紧张的时候,效果才明显。
7 楼 dzxiang 2010-05-04  
eueuy 写道
rainsilence 写道
var remoteObj = eval(response.responseText);
var mod = new remoteObj(TheParameters);

突然出现一个类,lz觉得这种方法好吗?
这个方法最早出现在2006年的csdn上,用于图片切换。
主要用途不是为了什么动态加载(lz的动态加载的理解还是有问题。难道你会把不会用到的<script标签加载进来吗?而且lz提出的挥之则去,怎么挥之则去?eval了还想去掉?所以相比script,如果单单只是从动态加载上考虑,可以说没有任何意义),而是为了核心js代码隐藏。但是Lz的这种做法还是太简单了,远远达不到代码隐藏的程度。


将MOD对象释放即可

与我现在的项目中用到的方式基本一样,我想了解一下楼主关于“将MOD对象释放”,是如何做的?
6 楼 eueuy 2010-05-03  
rainsilence 写道
var remoteObj = eval(response.responseText);
var mod = new remoteObj(TheParameters);

突然出现一个类,lz觉得这种方法好吗?
这个方法最早出现在2006年的csdn上,用于图片切换。
主要用途不是为了什么动态加载(lz的动态加载的理解还是有问题。难道你会把不会用到的<script标签加载进来吗?而且lz提出的挥之则去,怎么挥之则去?eval了还想去掉?所以相比script,如果单单只是从动态加载上考虑,可以说没有任何意义),而是为了核心js代码隐藏。但是Lz的这种做法还是太简单了,远远达不到代码隐藏的程度。


将MOD对象释放即可
5 楼 rainsilence 2010-05-03  
var remoteObj = eval(response.responseText);
var mod = new remoteObj(TheParameters);

突然出现一个类,lz觉得这种方法好吗?
这个方法最早出现在2006年的csdn上,用于图片切换。
主要用途不是为了什么动态加载(lz的动态加载的理解还是有问题。难道你会把不会用到的<script标签加载进来吗?而且lz提出的挥之则去,怎么挥之则去?eval了还想去掉?所以相比script,如果单单只是从动态加载上考虑,可以说没有任何意义),而是为了核心js代码隐藏。但是Lz的这种做法还是太简单了,远远达不到代码隐藏的程度。
4 楼 whiletrue 2010-05-02  
luolonghao 写道
ajax加载方式和iframe一样有跨域问题。

加载js文件就行了,跨域也行.不一定非要ajax
3 楼 luolonghao 2010-05-02  
ajax加载方式和iframe一样有跨域问题。
2 楼 hax 2010-05-02  
eval is evil

eval的执行context是在那个函数里,和你直接script标签加载是有所不同滴,存在潜在的问题。
1 楼 eueuy 2010-04-28  
抛砖引玉!!!!!!

相关推荐

    javascript完全学习手册1 源码

    3.1 JavaScript对象概述 43 3.1.1 对象的概念 43 3.1.2 使用JavaScript对象 基础知识 44 3.2 Array对象 46 3.2.1 创建Array对象 46 3.2.2 Array对象属性 47 3.2.3 Array对象方法 48 3.3 String对象 51 3.3.1 创建...

    javascript完全学习手册2 源码

    3.1.2 使用JavaScript对象基础知识 3.2 Array对象 3.2.1 创建Array对象 3.2.2 Array对象属性 3.2.3 Array对象方法 3.3 String对象 3.3.1 创建String对象 3.3.2 String对象属性 3.3.3 String对象方法...

    编写可维护的JavaScript(中文)

    运用本书中讲述的技巧和技术,可以使JavaScript团队编程从侠义的个人偏好的阴霾走出来,走向真正的高可维护性、高效能和高水准。 第一部分 编程风格 第1章 基本的格式化 1.1 缩进层级 1.2 语句结尾 1.3 行的...

    JavaScript基础教程第8版

    《JavaScript基础教程(第8版)》循序渐进地讲述了JavaScript及相关的CSS、DOM、Ajax、jQuery等技术。书中从JavaScript语言基础开始,分别讨论了图像、框架、浏览器窗口、表单、正则表达式、用户事件和cookie,并在上...

    JavaScript权威指南(第6版)中文文字版

    9.6 javascript中的面向对象技术 217 9.7 子类 230 9.8 ecmascript 5 中的类 239 9.9 模块 248 第10章 正则表达式的模式匹配 253 10.1 正则表达式的定义 253 10.2 用于模式匹配的string方法 261 10.3 regexp对象 263...

    JavaScript权威指南(第6版)

    9.6 JavaScript中的面向对象技术 9.7 子类 9.8 ECMAScript 5 中的类 9.9 模块 第10章 正则表达式的模式匹配 10.1 正则表达式的定义 10.2 用于模式匹配的String方法 10.3 RegExp对象 第11章 JavaScript的子集和扩展 ...

    JavaScript权威指南(第6版)中文版pdf+源代码

     9.6 JavaScript中的面向对象技术217  9.7 子类230  9.8 ECMAScript 5 中的类239  9.9 模块248  第10章 正则表达式的模式匹配253  10.1 正则表达式的定义253  10.2 用于模式匹配的String方法261  10.3 ...

    JavaScript权威指南(第6版)(附源码)

    9.6 JavaScript中的面向对象技术 9.7 子类 9.8 ECMAScript 5 中的类 9.9 模块 第10章 正则表达式的模式匹配 10.1 正则表达式的定义 10.2 用于模式匹配的String方法 10.3 RegExp对象 第11章 JavaScript的子集和扩展...

    程序天下:JavaScript实例自学手册

    1.20 在网页中动态添加Script脚本 1.21 用JavaScript随机修改页面的标题 1.22 判断网页加载完毕 1.23 嵌入网页的播放器 1.24 设置指定网页为主页 1.25 使用JavaScript传递页面参数 1.26 页面被冻结 第 2章 按钮特效 ...

    《JavaScript+DHTML语法与范例详解词典》源码

    如何通过JavaScript DOM对象来动态地操作整个HTML文档,对HTML元素进行添加、移动、修改或删除;XMLDOM的相关知识,以及如何通过JavaScript XML DOM对象来读取XML文件的数据,并添加、修改、删除XML文件元素。同时,...

    JavaScript权威指南(第6版)(中文版)

    9.6 JavaScript中的面向对象技术 9.7 子类 9.8 ECMAScript 5 中的类 9.9 模块 第10章 正则表达式的模式匹配 10.1 正则表达式的定义 10.2 用于模式匹配的String方法 10.3 RegExp对象 第11章 JavaScript的子集和扩展 ...

    JavaScript 权威指南(第四版).pdf

     9.6 JavaScript中的面向对象技术217  9.7 子类230  9.8 ECMAScript 5 中的类239  9.9 模块248  第10章 正则表达式的模式匹配253  10.1 正则表达式的定义253  10.2 用于模式匹配的String方法261  10.3 ...

    JavaScript学习指南

    《JavaScript学习指南(第2版)》系统地介绍了JavaScript的基本语法、基本对象、调试工具与排错技术、事件处理机制、浏览器对象模型/文档对象模型(BOM/DOM)等方面的知识,并通过一个复杂的示例深入探讨了Ajax应用。...

    javascript脚本化文档

    JavaScript代码可以访问和操作表示每个文档元素的对象。能够直接访问表示一个文档的内容的对象。这一能力是很强大的。但是这也使事情开始变得复杂起来。 一个文档对象模型或者说DOM就是一个API,它定义了如何访问...

    javascript

    javascript开发技术大全 第02章 开始JavaScript 第03章 数据类型 第04章 直接量 第05章 变量、常量与保留字 第06章 表达式与运算符 第07章 语句 第08章 对象简介 第09章 全局对象 第10章 函数 第11章 数组 第12章 ...

    《程序天下:JavaScript实例自学手册》光盘源码

    1.20 在网页中动态添加Script脚本 1.21 用JavaScript随机修改页面的标题 1.22 判断网页加载完毕 1.23 嵌入网页的播放器 1.24 设置指定网页为主页 1.25 使用JavaScript传递页面参数 1.26 页面被冻结 第 2章 按钮特效 ...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part1.rar

     1.3 JavaScript语法中常见的陷阱   1.3.1 区分大小写   1.3.2 单引号与双引号   1.3.3 换行   1.3.4 可选的分号和花括号   1.3.5 重载(并非真正的重载)   1.3.6 匿名函数   1.3.7 作用域...

    JavaScript实例精通

    6_2.htm 用JavaScript动态更换图像元素中的图像。 6_3.htm 利用搜索引擎引用来高亮页面关键字。 6_4.htm 使用匿名函数为定时器传递参数。 6_5.htm Web页面中的tooltip提示。 6_6.htm 在Web页面中控制其...

Global site tag (gtag.js) - Google Analytics