导言
差不多所有的 js 库都会对原生的 js 和 DOM 模型进行封装和扩展, jQuery 、 prototype 、 Ext 都有类似做法。
由于这些原生对象的相关方法注定会被大量地调用,对它们扩展得好与不好会直接关系到整个类库整体的性能。
经常看到有人说 Ext 的执行效率低下,笔者有时也有这种感觉,点个鼠标好像要延迟一下才有反应。但是说话得要有根据不是,不知道慢在哪里也不能跟着瞎起哄。(当然,也免得文章发出来被别人拍板砖,已经被拍过几次,汗啊 … )。
前一部分文章说了一下怎么用 VML 直接在网页上绘图,并且封装了一个小工具。这一部分的内容就先来看一下 Ext 对 js 的原生对象是如何封装和扩展的。
概览
从截图可以看到,在 Ext.js 这个文件中, Ext 对 Function 、 String 、 Number 、 Array 、 Date 。五个原生对象进行了扩展。这一篇先来分析一下对 Array 对象的扩展,并提出一个小小的疑惑。
Array 对象
js 的原生 Array 对象包含一个 length 属性和 12 个方法,简表如下:
concat() :添加元素
join() :将数组中的元素连接成一个字符串并返回
pop() :弹出最后一个元素
push(): 把一个元素加到数组最后
reverse(): 颠倒顺序
shift(): 移除第一个元素
slice() :返回子数组
splice(): 插入、删除或替换一个元素
toLocaleString(): 把数组转换成一个本地化的字符串
toString() :把数组转化成一个字符串
unshift() :在数组头部插入一个字符串
以上引自《 JavaScript 权威指南 第五版》,加粗部分是自己对照英文版的的翻译,原来的翻译是“把数组转换成一个局部字符串 ”,意思非常模糊,让人搞不懂。顺便再罗嗦一下,第五版的翻译不知道是干什么吃的,很多的东西不翻译或者直译,漏洞百出,建议想买这本书的人不要买这个版本。
在 Ext.js 里给 Array 对象扩展了两个方法,代码如下(注释已经翻译成中文):
Ext.applyIf(Array.prototype, {
/**
* 查找数组中是否存在指定的对象
* @param {Object} 需要查找的对象(的引用)
* @return {Number} 对象在数组中的位置下标 ( 如果不存在该对象,返回 -1)
*/
indexOf : function(o){
// 注意这里:是简单的线性查找,拿数组中的元素一个一个地去对比。
for (var i = 0, len = this.length; i < len; i++){
if(this[i] == o) return i;
}
return -1;
},
/**
* 从数组中删除指定的元素,如果该元素不存在,则什么事情都不做。
* @param {Object} o 需要删除对象的引用
* @return {Array} 返回删除后的数组
*/
remove : function(o){
var index = this.indexOf(o);
if(index != -1){
this.splice(index, 1);
}
return this;
}
});
在注释里面加注意的地方说到 indexOf() 方法的查找问题,可以看到,这里的 indexOf() 使用的是简单的线性查找, remove() 方法调用了这个 indexOf() 方法来查找对象在数组中的位置。这个地方的效率很低,也就是说,如果我们往一个数组里面保存了很多的对象,然后在另外的地方频繁调用数组的 indexOf() 或者 remove() 方法的时候,速度就会比较慢。所以有人老说 Ext 存在效率问题,我想,这个所谓的“效率问题”不是哪一处地方造就的,而是由诸多效率差的小细节积累而成的,假如我们实在没有办法去改变什么,那么至少要注意到这些地方,避免陷阱,这是这篇文的主旨所在。
由于线性查找效率是 O(n) ,所以,在数据量稍大的时候,需要寻找替代 Array 的办法。有很多文章说过关于 Array 的这个问题,包括《权威指南》,办法是模拟一个 Hash 表。基本的思路如下:
var mp={};
mp['key1']={name:'damoqiongqiu',age:'25',QQ:'88403922'};
mp['key2']={name:'damoqiongqiu',age:'26',QQ:'88403922'};
alert(mp.key2.name);
这样处理,可以提升查找效率,效率可能接进 O(1) 。(顺便说一句,效率只能接进是 O(1) ,因为 js 内部通过这个字符串型的 key 去找到 value 也是需要花时间的,即使是通过类似Java或C++的Hash算法,也是需要通过key来算HashCode的不是?通过HashCode找到对应的Hash桶之后还是一个线性查找。)
《指南》里面还有提到一种伪数组:
var a={}
while(i<10){
a[i]=i*I;
i++
}
a.length=i;
如果情况比较好,事先知道插入的元素是有序的就可以使用其它的查找算法,像二分查找之类的,这样的情况估计不容易遇到,除非上天恩赐 J ,否则还讨论个什么劲?
当然,有些情况必须用到数组,除此没有办法,那还有什么好说的,用呗!但是,在确确实实对效率有很多要求的地方,需要考虑类似的变通方法。
一个疑惑:
经常看到有人问, js 里面的 == 和 === 有什么区别,翻了一下书,大概的意思是:
=== 是比较两个值是不是完全相等。
而如果用 == 来比较,假如两个值是同一类型,就用 === 比较它们是否等同。否则如果两个值是以下组合时,将非 Number 型强转成 Nunber 再来比较。
String 、 Number
Number 、 Boolean
也就是说, ”1”==true 是正确的, 1==true 也是正确的,如此这般。
如果一个值是对象,另一个值是 String 时,将对象转成 String ,再来比较这两个 String 是不是相等。
OK ,有了上面的简单解释,我们来测试一下 Ext 中 Array 的 indexOf() 方法。
首先来个简单的:
Ext.onReady(function(){
// 基础语义测试
var test="1";
alert(test==true);
})
没有问题,出来一个 true 。
再来个稍微复杂点的,先向数组里面插入 1000 个对象,然后在第六个元素放一个布尔型的 true 值,然后自己来遍历数组,看看有没有元素和字符型的 ’1’ 相等:
Ext.onReady(function(){
// 自定义数组测试
var test="1";
var arr=[];
for(var i=0;i<1000;i++){
var temp=(i==5)?true:{id:i};
arr.push(temp)
}
for (var i = 0, len = arr.length; i < len; i++){
if(arr[i] ==test){
alert(i);
break;
}
}
})
好,没有问题,找到了第六个元素。
来测 Array 的 indexOf() 方法,从 Ext 的源码里面可以看到, Array 的 indexOf() 方法和我们上面自己遍历的方法是一样的,但是,神奇的事情发生了,看代码:
Ext.onReady(function(){
// 自定义数组测试
var test="1";
var arr=[];
for(var i=0;i<1000;i++){
var temp=(i==5)?true:{id:i};
arr.push(temp)
}
// 测试 Ext 封装 Array 的 indexOf() 方法
alert(arr.indexOf(test));
})
按道理来说,这里也应该能够弹出来元素的位置,但是,结果是,没有找到这个元素。。。可视,这是为什么呢?期待牛人给出解释,不甚感谢!
这个问题已解决,多谢zbm2001的解释,我自己又测试了一下,只有FireFox实现了Array原生的indexOf()方法,而IE、Safari、Opera都没有原生实现。Ext在扩展的时候用的是applyIf()方法,所以在存在原生实现的时候不会拿Ext的实现去覆盖。
分享到:
相关推荐
作人 :?聊仔 安??明: 1、修改 config.cgi 中的相关设定。 2、在cgi-bin目?外存放images中的img1和img2,??目?路???於config.cgi中,否?不能正常?示。 3、?於cgi的安?和架?不在本文中探?。 4、任何bug和??...
注?信息: 用?名:大眼仔~旭(Anan) 注??:7069-3890-1986-9697 注??:3647-7903-0568-7523 注??:5497-5001-9890-1336 Magic NTFS Recovery
Magic Partition Recovery 注?信息: 用?名:大眼仔~旭(Anan) 注??:9419-0906-9494-0679 注??:8642-4141-6687-0186 注??:5157-3585-0291-2592
总的来说,这个模板包含了一套完整的后台管理界面,使用了流行的Bootstrap框架,提供了响应式设计,确保在各种设备上都能良好显示。开发者可以快速搭建后台管理系统,通过修改HTML、CSS和JavaScript文件来定制自己的...
UI框架是开发者用来快速设计和开发用户界面的一种工具,通常包括预定义的样式、组件和交互模式,能够帮助开发者节省时间和提高工作效率。 在提供的文件名列表中,我们可以看到该框架包含以下主要部分: 1. `??????...
OA系统是为了提高医疗机构内部工作效率,整合资源而设计的信息管理系统。 描述部分与标题基本一致,强调这是一个HTML源码,适用于H5(第五代超文本标记语言)的整站构建。这意味着模板遵循现代网页开发标准,支持...
【标题】"蓝色精美的booststrap响应式后台模板源码下载HTML源码H5整站.zip" 提供的是一款基于...在实际应用中,开发者还可以根据需求自定义CSS皮肤,调整布局,或者扩展JavaScript功能,以满足特定项目的需求。
\assets\js\date-time\:JavaScript文件夹,包含项目所需的脚本文件,其中"date-time"可能是一个专门处理日期和时间的子目录。 综合以上信息,我们可以得知这个OA办公系统后台管理界面模板包含了一个完整的前端结构...
自动化测试脚本能够显著提高测试效率,减少手动测试的工作量,并确保产品在不同环境下的稳定性。这里我们将深入探讨“自动化测试的脚本自动执行浏览器的操作”,主要关注使用Selenium这一强大的工具。 Selenium 是...
EXTJS 4.2.0 Beta 版本是EXTJS框架的一个重要里程碑,它在原有的4.1.x系列基础上引入了新的特性和改进。EXTJS是一个强大的JavaScript库,专为构建交互式、数据驱动的Web应用程序而设计。4.2.0测试版尤其值得关注,...
用脚本分析大流量数据(建议用perl); 内容:Web流量分析 搭建Web服务器和DNS服务器,要求Web服务器IP地址为“xx.xx.xx.学号的后三位”,要求DNS服务器IP地址为“xx.xx. 学号的后三位. xx”;用Web服务器、DNS...
【牛仔IIS日志蜘蛛爬行记录分析器 v1.1】是一款专门针对IIS(Internet Information Services)服务器日志进行分析的工具,主要用于帮助网站管理员了解搜索引擎蜘蛛的爬行行为,从而优化网站的SEO策略。IIS是微软公司...
在实际应用中,数据可视化大屏通常会包含多个模块,如实时数据监控、趋势分析、预警提示等,每个模块都由独立的Vue组件构成,这样既能保证代码的清晰性,又能提高开发效率。ECharts提供的丰富的图表选项和交互能力,...
"扩展ACL的应用实例及解析" 扩展ACL(Access Control List,访问控制列表)是一种网络安全机制,用于控制网络流量,保护网络资源。扩展ACL是标准ACL的升级版本,具有更多的灵活性和功能性。 扩展ACL的分类: 1. ...
安全工作者在业务中经常会用到fofa搜集甲方资产(子域名,旁站,c段等),该脚本使用python3编写,分为API版(最多只能获取1w条数据)和爬虫版(有多少数据就能获取多少数据,需要cookie),且都为命令行参数形式。...
在.NET开发中,Entity Framework(简称EF)是一个强大的对象关系映射(ORM)框架,它允许开发者使用面向对象的编程语言来操作数据库。在处理大量数据插入时,传统的逐条插入方式可能会导致性能低下,此时我们可以...
- 在`js`目录下的脚本文件中添加或修改逻辑,实现后台管理的各种功能,如数据检索、编辑保存、权限控制等。 - 根据业务需求,调整或复制`list.html`、`column.html`等HTML模板,创建新的视图页面。 - 将图片资源替换...
通过《明仔PHP面向对象(六日通)教程》的学习,你不仅能够掌握PHP面向对象的基本语法,还能了解如何在实际项目中应用这些概念,提升你的编程技能。同时,教程中的"说明.htm"文件可能会提供课程的使用指南、学习路径...