‘JavaScript’ Category Archives
一
jQuery 1.4新增与更新
作者: boke ,分类: JavaScript
jQuery Minified (23kb Gzipped)
jQuery Development(156kb)
1.4重要新特性:
- 常用方法的性能大幅提升:重写了大部分较早期的函数;
- 更容易使用的设置函数(setter function):为所有对象新增了许多易用的设置函数;
- 对Ajax的改进:引入了许多Ajax和JSON处理方面的更新,包括HTML5元素的序列化;
- attribute(改进了.attr()的性能)、jQuery()核心函数、CSS(.css()性能有两倍提升)、特效和事件、DOM操作等也有显著改进
此次共有41个改动,包括25个更新,16个新增方法。参见:http://api.jquery.com/category/version/1.4/ 。网上看到金山简单翻译的jQuery 1.4新增与更新的文章。
六
Javascript类及对象创建
作者: boke ,分类: JavaScript
关于js里的类与c#等的区别,不在这里提,只说一下怎么创建类及对象。js里创建类及对象很简单,例如:
function Room(c){
this.windows = c;
this.owner = "A";
this.show = function(){
alert(this.windows);
}
}
var r1 = new Room(4);
var r2 = new Room(2);
像这样创建对象时,每次都会创建一个show()函数的副本,但其实r1和r2两个对象是可以共享同一个show()的,这样就浪费了内存。
当然,也有不浪费内存的写法,这就要用到对象的prototype属性,可以把它看成创建新对象所依赖的原型。当new时,原型的所有属性都被赋予新创建的对象,新对象中只有一个指向类中某个函数的指针,不会再生成一个副本。如下:
function Room(){
};
Room.prototype.windows = 2;
Room.prototype.owner = "A";
Room.prototype.show = function(){
alert(this.windows);
}
var r1 = new Room();
var r2 = new Room();
这样虽然没浪费内存,但当你想给r1做一些改动,比如,r1.owner=”B”,这时,r2也会被改动,这样肯定不行。
啊,不是说js里创建类和对象很简单嘛,怎么还有这么多问题呀!别急,其实第一个例子已经成功达到目的了,我们这不是在寻找更合理的创建对象的方法嘛。
说说我常用的两种创建对象的简单方法,不知道是不是最好的,依我目前所知,应该是最简单通用的了。
这有一种,学名叫啥我忘了,似乎应该有个学名吧。其实就是前面两种方法的混合使用,用第一种方法定义对象的属性,用prototype原型链定义对象的方法。再看上面那个例子:
function Room(c){
this.windows = c;
this.owner = "A";
}
Room.prototype.show = function(){
alert(this.windows);
}
var r1 = new Room(4);
var r2 = new Room(2);
r1.owner = "B";
alert(r1.owner);//输出B
alert(r2.owner);//输出A
恩,就这样。既不浪费,又可以针对具体对象做修改。还行,嚎~
再来看看另外一种方法,直接创建实例对象。如下:
Room={
init:function(c){
this.windows = c;
this.owner = "A";
},
show:function(){
alert(this.windows);
}
}
Room.init(4);
Room.owner = "B";
Room.show();
这种方式直接创建了一个对象,自然也就不用new了。不会像第一个例子那样浪费内存,也不会出现第二个例子那样情况(别问我为什么)。
在大多数情况下,我会使用第3,4个例子的方式创建类及对象,简单,通用,雅俗共赏。至于怎么用这两种方式?这就要看情况了。举例来说,页面里有一个菜单栏menu,菜单栏里会有多个菜单项menuItem,这样我就会像第四个例子那样创建一个menu对象,然后像第三个例子那样创建多个menuItem对象,并将其添加到menu里。
好久没写了,不知道容不容易看懂。上面仅仅是我的理解,哪里有问题,忘高手指正。
六
javascript性能优化(不定期整理)
作者: boke ,分类: JavaScript
javascript的性能优化通常包括两个方面,一是代码体积减小带来的下载时间减少,二是代码效率提高带来的执行时间减少。
关于代码体积的改善
javascript不同于c、c++这样的编译语言,开发人员不需要考虑变量名长度及注释等,因为在编译时这些都会被删除或替换。javascript的所有内容都需要下载到客户端执行,这些无意义的东西最好还是删除或缩小为妙。下面常用的减少代码体积的方法:
1、删除注释。
2、删除空格,制表符,换行符。
3、替换变量名。
当然,上面的三种情况不需要手工去做的,我们可以使用一些压缩工具JSMin,YUI Compressor,还有我正在用的Packer,TB Compressor等。经研究表明,即使是通过Gzip压缩后的代码,如果通过上面那些工具先进行一步压缩,仍可减少5%以上的体积。
4、避免使用布尔值。在js里true等于1,false等于0。
5、缩短否定检测。js代码里有许多检测某个值是否有效的判断语句,像
if(typeof g == undefined){
return;
}
if(g == null){
return;
}
if(g == false){
return;
}
if (g == 0){
return;
}
上面的语句除非变量g可以为0,或没有在作用域链中出现过,我们要用0和undefined判断,否则,这样写更简洁:
if (!g){
retrun;
}
关于代码效率的改善
=======================================(分割线,以上2009-07-08)
1、仔细检查函数中所有使用的变量,如果有一个变量不是当前作用域定义的,而且使用了不止一次,那么我们就应该把这个变量保存在局部变量中,而使用这个局部变量来进行读写操作。这样可以帮助我们将作用域外的变量的搜索深度减少到1。这对全局变量尤为重要,因为全局变量总是被放到作用域链的最后位置来搜索。
2、避免使用with语句。因为它会修改执行上下文(Execution Context)的作用域链,在最前面添加一个对象(Variable Object)。这就意味着在执行with的过程中,实际上的局部变量都被移到作用域链上的第二个位置,这会带来性能上的损失。
3、如果你确定一段代码肯定会抛出异常,那么就要避免使用try-catch,因为catch分支在作用域链上的处理方法和with是一样的。但try分支的代码是没有性能损失的,所以还是建议用try-catch来捕获那些不可预知的错误。
======================================(2009-06-19的分割线)
4、使用join代替“+”或“for”连接字符串。例如:
var wrap = [ vanillaDiv
, '<div style="position:absolute;top:0px;left:0px;padding:0px;'
, 'margin:0px;overflow:visible;height:'
, Dock.height, 'px;width:', Dock.width
, 'px;"></div></div>'
].join('');
现代浏览器对“+”连接字符串都做了相应的优化,可以根据应用情况和自己喜好权衡使用。这有文章Fastest way to build an HTML string,作者James Padolsey,一个很牛逼的18岁小孩。
5、将可反复利用的内容放在循环体外部。例如:
下面这个函数从DOM树中选择一个元素,然后对这个元素做一些事情。如果像下面这样,需要每次都从树中去找container这个元素,而且会每次都进行someArray的长度计算。
for(var i = 0; i < someArray.length; i++) {
var container = document.getElementById('container');
dosomething();
}
改进一下,写成下面这样,达到了同样的目的,却不用每次搜索DOM树了,也不用每次都计算someArray的长度了。
var container = document.getElementById('container');
for(var i = 0, len = someArray.length; i < len; i++) {
dosomething();
}
类似的应用还有地图蒙板这个例子,每次鼠标移动都要调用mbCtrl.move()这个函数,可以看一下index.js里的112-115行,如果直接这样用$(“#mapContainer > div:nth-child(3)”)选择器选择,每次鼠标移动都要搜索DOM树,实际应用时效率奇低呀。改进一下,
var mbCtrl = {
init:function(){
this.div3=$("#mapContainer > div:nth-child(3)");
},
move:function(){
this.div3=css({top:'0',left:'0',width:this.mwth,height:tc,display:"block",background:"#f00"});
}
}
在一开始就把要操作的对象选择出来,缓存起来,这样一个小改动,在一些浏览器(ie)里有成百倍的效率提高。
6、用{}代替new Object(),用[]代替new Array()。
这个不多说了,就是使用var obj={},arr=[]代替var obj=new Object(),arr=new Array(),这样就不用再进行一次实例化了,而且减少了代码体积。至于到底啥时候用object,啥时候用array,”A common error in JavaScript programs is to use an object when an array is required or an array when an object is required. The rule is simple: when the property names are small sequential integers, you should use an array. Otherwise, use an object.” – Douglas Crockford
=============================================(2009-07-03分割线)
7、if与switch的使用。if语句在js里应用很多,因为用户可能的操作习惯实在是没有规律,应该尽量减少判断执行次数。通常采用的优化方式有两种,最大可能排最前和分组判断。举个例子:
if (value > 3){
if (value == 5){
return result5;
}
else if (value == 4){
return result4;
}
else{
return result6;
}
}
else{
if (!value){
return result0;
}
else{
if (value == 1){
return result1;
}
else if (value == 2){
return result2;
}
else{
return result3;
}
}
}
让面的例子对if判断进行了分组,而且把最可能出现的判断条件放在了前面。当判断条件较多时,使用switch语句的效率要好于if语句,可以根据情况尽量使用switch语句处理。js里还有个好处就是case语句里可以使用任何类型的值,例如:
switch(value){
case "yellow":
alert('fuck');
break;
case "green":
alert('yada');
break;
case 3:
alert("what");
break;
default:
alert("go to hell");
}
这里还有个据说更好的方法:
switch(value){
case 0:
return result0;
case 1:
return result1;
case 2:
return result2;
case 3:
return result3;
case 4:
return result4;
case 5:
return result5;
}
var results = [result0, result1, result2, result3, result4, result5];
return results[value];
可以看出使用switch和数组达到了相同目的,但使用数组的效率更高一些。这里有个测试地址http://www.nczonline.net/experiments/javascript/performance/conditional-branching/
8、使用更有效率的循环写法。据说能节省50%的执行时间:
var values = [1,2,3,4,5];
var length = values.length;
//for loop
for (var i=length; i--;){
process(values[i]);
}
//do-while loop
var j=length;
do {
process(values[--j]);
} while (j);
//while loop
var k=length;
while (k--){
process(values[k]);
}
至于for-in循环,再对对象进行操作时很好用,但比较低效,所以除非要遍历对象,否则还是不要用它了。
9、优先使用javascript内置方法。js的内置方法都是在浏览器里的,通常都是由C++编译的,这比自己写的js方法要快很多很多。
10、最小化语句数量。对于js这种解释性语言,有理由相信语句越少,执行所需的时间越短。有几个例子:
var a = 3; var b = "yada"; var c = [1,2,3]; var d = new Date(); var name = names[i]; i++; var obj = new Object(); obj.color = "red"; obj.num = 5;
优化一下:
var a = 3, b = "yada", c = [1,2,3], d = new Date();
var name = names[i++];
var obj = {color:"red", num:5};
三
javascript键盘事件总结
作者: boke ,分类: JavaScript
这两天做了一个AutoComplete,顺便研究了一下js的键盘事件,简单总结一下学到的东西
| Firefox | 返回键值 |
| keyCode(keypress) | 功能键(Shift,Ctrl,Alt,PrintScreen,ScrollLock无返回值)返回正确值,以外的所有键值皆为0 |
| keyCode(keydown) | 返回除PrintScreen外所有键值,字母键皆以大写状态显示键值(65-90) |
| keyCode(keyup) | 返回除PrintScreen外所有键值,字母键皆以大写状态显示键值(65-90) |
| charCode(keypress) | 返回字符键大小写键值(65-90,97-122),Shift,Ctrl,Alt,PrintScreen, ScrollLock无返回值,其他所有键值为0 |
| charCode(keydown) | 所有键值为0 |
| charCode(keyup) | 所有键值为0 |
| IE | 返回键值 |
| keyCode(keypress) | 返回出系统按键外所有字符键的正确值(区分大小写状态65-90,97-122) |
| keyCode(keydown) | 返回除PrintScreen外所有键值,字母键皆以大写状态显示键值(65-90) |
| keyCode(keyup) | 返回除PrintScreen外所有键值,字母键皆以大写状态显示键值(65-90) |
| charCode | IE不支持该属性 |
关于三个键盘事件的区别网上通常这样解释
onkeydown 在用户按下任何键盘键(包括系统按钮,如箭头键和功能键)时发生。
onkeypress 在用户按下并放开任何字母数字键时发生。系统按钮(例如,箭头键和功能键)无法得到识别。
onkeyup 在用户放开任何先前按下的键盘键时发生。
通俗的理解可以像以上那样,但其实并不是如此,我的试验也证实像上下键、退格、回车等在onkeypress事件里也可以在部分浏览器中(如:firefox)被识别。这其中包含keycode向charcode转化,系统对输入流接收、处理、输出等的复杂过程,并且不同浏览器的处理也不尽相同。应该在实际应用中具体把握,明天去公司把我写的测试程序补充上。
特别注意一下,在Opera下,对于onkeydown的默认行为是不能用event.preventDefault()来取消的。
3.25更新:
我用的两个测试文件,key.html能测试每个事件中包含的内容,keyCode等,key0.html能测试键盘事件触发顺序等。
二
javascript的字符串比较
作者: boke ,分类: JavaScript
今天写程序时发现了一个以前虽然知道但总没引起我注意的问题,记录一下,防止再犯。
代码像下面这样:
<script type="text/javascript">
var aheight ="290px";
var bheight;
var val = (bheight>aheight)?aheight:bheight;
alert(val);
</script>
很简单,元素a的高是290px,元素b的高是变动的,val的值等于a和b中高度小的。恩,好像没啥不对。
bheight="210px",试试 ,val="210px",对;bheight="160px",再试,val="160px",还对;那么bheight="99px"呢?val的值是99px吗?错了,这时候alert出了290px。
呵呵,忘了javascript的字符串比较是从第一个字符开始一个一个字符比较的了,当两个字符相等时接着比较下一个,当出现不相等的就停下。在这个例子里,"29"大于"21",所以"290px">"210px","2"大于"1",所以"290px">"160px",而9大于2,所以"99px">"290px"哈。