omiga

简单就好

一些有用的JavaScript函数(3)

发表评论»

获取页面窗口大小

function getPageSize(){
 var size = [];
 size.push(window.innerWidth || document.documentElement.clientWidth);
 size.push(window.innerHeight || document.documentElement.clientHeight);
 return size;
}

获取鼠标坐标

function getMousePosition(e){
 var p = [];
 e = e || window.event;
 p.push(e.clientX);
 p.push(e.clientY);
 return p;
}

阻止事件冒泡

function stopBubble(e){
 if(e&&e.stopPropagation){
  e.stopPropagation();
 }else{
  window.event.cancelBubble = true;
 }
}

阻止浏览器默认动作

function stopDefault(e){
 if (e&&e.preventDefault){
  e.preventDefault();
 }
 else{
  window.event.returnValue = false;
 }
 return false;
}

获取json长度

function getJsonLength(jsonData){
 var jsonLength = 0;
 for(var item in jsonData) jsonLength++;
  return jsonLength;
 }

其实都是些很简单的函数,记录下来,减少重复操作,提高效率!

一些有用的JavaScript函数(2)

发表评论»

重写原来那个获取对象在其兄弟节点中的索引的函数。原来的通过设置id来使对象具有某种特征,这种做法具有极大的危险性。

function getElementIndex(e){
 var objParent = e.parentNode;
 var objSiblings = objParent.getElementsByTagName(e.tagName);
 e.setAttribute("flag","crt_e");
 for(var i=0; i
  if(objSiblings[i].getAttribute("flag")==="crt_e"){
   objSiblings[i].removeAttribute("flag");
   return i;
  }
 }
}

一个获取当前北京时间的时间类。不知道为什么JS中没有提供对小时支持的函数~···

function Time(){
 var nowTime = new Date();
 this.year = nowTime.getUTCFullYear();
 this.month = nowTime.getUTCMonth()+1;
 this.date = nowTime.getUTCDate();
 this.hours = Math.floor((nowTime.getTime()/(1000*60*60))%24)+8;
 this.minutes = nowTime.getUTCMinutes();
 this.seconds = nowTime.getUTCSeconds();
}

javascript性能优化

3条评论»

很久就想总结一下关于javascript性能优化方面的一些东西,平时也有注意收集这方面的资料。把del.icio.us里的收藏的东西翻出来看一遍,才惊奇地发现,这些所谓的优化方法大多出自《javascript高级程序设计》一书,当然也有个别
不一样的。总之这本书上关于javascript性能优化的内容足足用了近20页来进行阐述,所以今天我也照本宣科地来介绍一下,同时收录其他方法。

javascript的性能优化应分为两部分:下载时间和执行时间。

下载时间

javascript作为一种解释性语言不同于其他编程语言。在诸如java,c,c++的语言中,开发人员根本无需考虑变量名的长度以及长篇大论的注释,因为这些在编译时都会被删除。

但是web浏览器下载的是javascript的源代码,你编写的javascript程序文件会原模原样地下载到客户端。而这些长变量名和注释就会影响脚本的下载时间。单个TCP-IP包中能放入的字节数是1160,所以最好将每个javascript文件的大小控制在1160字节以内以获取最优的下载时间。

javascript文件中的任何字节,不管是空格,还是换行都会影响javascript文件的下载时间,所以在部署任何javascript文件之前,都应该尽可能地优化脚本文件的体积。以下是一些常用的优化javascript文件大小的方法:

1、删除注释

脚本中的任何注释都应该在部署之前被删除。虽然注释对于开发人员来说意义重大,但在部署时这些注释对客户端用户是没有任何实质意义的,而更可怕的是很多javascript源代码中的注释会比代码多得多。因此删除注释是所见javascript文件大小最为方便有效的途径。

2、删除制表符和空格

又规律地缩进代码有增强代码的可阅读性,但是浏览器/客户端用户并不需要这些额外的制表符和可个,所以最好删除它们,包括函数参数,赋值语句和比较操作符之间的空格:

function doSomething ( arg1, arg2, arg3 ){
 alert(arg1 + arg2 + arg3);
}
function doSomething(arg1,arg2,arg3){alert(arg1+arg2+arg3);}

3、删除所有换行

和前一条规则一样,只要你在程序的每行结尾都正确地添加了分号,那么就不需要再添加换行符了。

4、替换变量名

此方法很无聊,大致做法就是将所有变量名替换成无意义的简短变量名。

要手动地完成以上四步,在实际中可能会有一定的难度,那么下面的一些链接可能对你有所帮助。

ECMAScript Cruncher:http://saltstorm.net/depo/esc/
JSMin(The JavaScript Minifier): http://www.crockford.com/javascript/jsmin.html
Online JavaScript Compressor:http://dean.edwards.name/packer/

5、替换布尔值

对于比较来说,true等译1,false等于0。因此可以将字面量的true都用1来替换,而false用0来替换,进而较少一定的字节数。

6、缩短否定检测

代码中常常会出现检测某个值时候有效的语句。而大部分否定测试所做的就是判断某个变量是否为undefined、null或者false,如下:

if(oTest != undefined){
 // dosomething
}
if(oTest != null){
 // dosomething
}
if(oTest != false){
 // dosomething
}
//这样写更简洁
if(!oTest){
 // dosomethin
}

7、使用数组和对象字面量

var aTest = new Array;
var oTest = new Object;
oTest.pro1 = "pro1"
oTest.pro2 = "pro2";

和下面的代码作用是完全相同的,但是下面的代码可以节省更多的字节。

var aTest = [];
var oTest = {pro1:"pro1",pro2:"pro2"};

执行时间

javascript是一种解释性语言,它的执行速度要大大慢于编译型语言。据测试,javascript的执行效率要比编译型的C程序慢5000倍;比解释型的Java慢100倍;比解释型的Perl慢10倍。但是我们仍然可以通过一些简单的事情来提高javascript的效率,同时这也显得更加重要。

1、使用局部变量

在函数中,总是使用var来定义变量。无论何时使用var都会在当前的范围类创建一个局部变量。如果不使用var来定义变量,那么变量会被创建在window范围内,那么每次使用这个变量的时候,解释程序都会搜索整个范围树。同时全局变量要在页面从浏览器中卸载后才销毁,而局部变量在函数执行完毕即可销毁,过多的全局变量增加了不必要的内存消耗。

2、避免使用with语句

使用with语句能够减少一定的代码长度,但是在使用with语句时,要强制解释程序不仅在范围树内查找局部变量,还强制检测每个变量及指定的对象,看其是否为特性。因为,我们也可以在函数中定义同明的变量。

3、选择正确的算法

只要有可能就应该用局部变量或者数字索引的数组来替代命名特性。如果命名特性要多次使用,就先将它的值存储在局部变量中,一避免多次使用线性算法请求命名特性的值。

var aValues = [1,2,3,4,5,6,7];
function testFunc(){
 for(var i=0, iCount=aValues.length; i++){
  alert(i + "/" + iCount + "=" + aValues[i]);
 }
}

4、反转循环

循环在各种编程语言中得到大量应用,所以保持循环的高效性尤为重要。按照反向的顺序进行循环迭代是一种有效的方法。

for(var i=aValues.length-1; i >= 0; i--){
 //do something
}

反转循环有利于减低算法的复杂度。它用常数0作为循环控制语句以减小执行时间。

5、翻转循环

用do..while循环来替代while循环以进一步减少执行时间。假设有如下while循环:

var i=0;
 while(i < aValues.length){
  //do something
 i++;
}

可用do..while循环重写上面的代码而不改变行为:

var i=0;
do{
 //do something
 i++;
}while(i < aValues.length)

这段代码比用while循环更快,因为它用循环反转来进一步地优化:

var i=aValues.length-1;
do{
 //do something
 i--;
}while(i>=0)

也可以将自减操作直接放进控制语句中,以减少额外的语句。

var i=aValues.length-1;
do{
 //do somethin
}while(--i>=0)

这个循环已经被完全优化了

6、展开循环

可以考虑将循环展开,一次执行多个语句。考虑如下for循环例子:

var sum = 0;var aValues=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for(var i=0; i<aValues.length; i++){
 sum+=aValues[i];
}

循环总共要执行20次,每次都是对变量sum进行增量操作,但是可以这样写:

var aValues=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var sum = 0;
for(var i=0; i<aValues.length; i++){
 sum+=aValues[i];
 i++;
 sum+=aValues[i];
 i++;
 sum+=aValues[i];
 i++;
 sum+=aValues[i];
 i++;
 sum+=aValues[i];
 i++;
}

在循环体内做了五次增量。每次增量后,都对变量i加1,所以多数组的遍历与原来是一致的,但是控制语句只执行了四次,减少了执行时间。当然还可以继续优化:

var aValues=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var sum = 0;
for(var i=0; i<aValues.length; i++){
 sum+=aValues[i++];
 sum+=aValues[i++];
 sum+=aValues[i++];
 sum+=aValues[i++];
 sum+=aValues[i++];
}

关于此算法的更多信息可以参考这里http://home.earthlink.net/~kendrasg/info/js_opt/

7、优化if语句

使用if语句和多个else语句时,一定要把最有可能的情况放在第一个,然后是第二可能出现的情况,如此排列,这样就减少了要进行多次测试才能遇到正确条件的情况。

同时也要尽量减少else if语句的数量,并且将条件按照二叉树的方式进行排列。例如:

if(iNum>0){
if(iNum>10){
 alert("Between 0 and 10");
}else{
 if(iNum>20){
  alert("Between 10 and 20");
 }else{
  if(iNum<30){
   alert("Between 20 and 30");
  }else{
   alert("Greater than or equal to 30");
  }
 }
}
}else{
 alert("Less than or equal to 0");
}

8、switch和if

一般来说超过两种情况时,最好使用switch语句。常用switch来代替if语句,最高可令执行快10倍。在javascript中就更加可以从中获益,因为case语句可以使用任何类型的值。

9、避免字符串连接

一旦一次要使用多个字符串的连接(比如,大于五个),最好使用如下方式:

var buf = new Array();
for(var i = 0; i < 100; i++){
 buf.push(i.toString());
}
var all = buf.join("");

10、优先使用内置方法

只要可能,就应该考虑优先使用内置方法。因为内置方法是用C++或者C之类的语言编译的,运行起来比必须实时编译的javascript要高效的多。比如你可能像要自己编写一个求阶乘的函数,但是实际上你应该使用javascript内置的Math.pow()方法。

11、存储常用的值

当多次使用到一个值得时候,可先将其存储在局部变量中以便快速访问。尤其对于通常使用对象的特性来进行访问的值更加重要。如:

oDiv1.style.left = document.body.clientWidth;
oDiv2.style.left = document.body.clientWidth;

document.body.clientWidth在该例中被使用了两次,但它是使用命名特性(属于极其昂贵的操作)来获取的。可以使用局部变量来重写这段代码:

var iClientWidth = document.body.clientWidth;
oDiv1.style.left = iClientWidth;
oDiv2.style.left = iClientWidth;

12、最小化语句数量

我们有理由相信,脚本中语句越少,执行所需要的时间越短。很多方法可以将javascript中的语句数量减到最少,比如定义变量时,处理迭代数字时,使用数组和对象字面量时。

多个变量的定义可用一个var语句来替代:

var iFive = 5, sColor = "red", aValues = [1,2,3], oDate = new Date();

插入迭代子

使用迭代子(在不同位置上加减的值)时,尽可能合并语句。考虑下面代码:

var sName = aValues[i];
i++;

这样写更简短:

var sName = aValues[i++];

13、节约使用DOM

不管是添加、删除或者是其他对页面DOM内部结构的更改,都会导致整个页面的重新渲染,带来的是明显的时间消耗。解决这个问题的方法是尽可能地对不在DOM文档中的元素节点进行操作。如下例子:

var oUL = document.getElementById("ulItems");
for(var i=0; i<10; i++){
 var oLI = document.createElement("li");
 oUL.appendChild(oLI);    //I
 oLI.appendChild(document.createTextNode("Item "+i));    //II
}

每次执行I都会对整个页面重新渲染一次,执行II又会对整个页面重新渲染一次,总共会有20次的对页面的渲染。我们大可使用文档碎片来保存所有列表项,最后再一起添加到文档中。

var oUL = document.getElementById("ulItems");
var oFragment = document.createDocumentFragment();
for(var i=0; i<10; i++){
 var oLI = document.createElement("li");
 oLI.appendChild(document.createTextNode("Item "+i));
 oFragment.appendChild(oLI);
}
oUL.appendChild(oFragment);

这样对文档中DOM树的操作就只有一次。

其他一些优化方法

1、不要使用eval

使用eval相当于在运行时再次调用解释引擎对内容进行运行,需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版(关于闭包的内容请参考函数式编程的有关内容)

2、类型转换

类型转换是大家常犯的错误,因为JavaScript是动态类型语言,你不能指定变量的类型。

  1. 把数字转换成字符串,应用”" + 1,虽然看起来比较丑一点,但事实上这个效率是最高的,性能上来说:(“” + ) > String() > .toString() > new String()这条其实和下面的“直接量”有点类似,尽量使用编译时就能使用的内部操作要比运行时使用的用户操作要快。String()属于内部函数,所以速度很快,而.toString()要查询原型中的函数,所以速度逊色一些,new String()用于返回一个精确的副本。
  2. 浮点数转换成整型,这个更容易出错,很多人喜欢使用parseInt(),其实parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,我们应该使用Math.floor()或者Math.round()。另外,和第二节的对象查找中的问题不一样,Math是内部对象,所以Math.floor()其实并没有多少查询方法和调用的时间,速度是最快的。
  3. 对于自定义的对象,如果定义了toString()方法来进行类型转换的话,推荐显式调用toString(),因为内部的操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String,所以直接调用这个方法效率会更高

3、字符串遍历操作

对字符串进行循环操作,譬如替换、查找,应使用正则表达式,因为本身JavaScript的循环速度就比较慢,而正则表达式的操作是用C写成的语言的API,性能很好。

4、DOM相关

  1. 插入HTML 很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效率较低,如果需要直接插入HTML,可以找一个容器元素,比如指定一个div或者span,并设置他们的innerHTML来将自己的HTML代码插入到页面中。
  2. 创建节点 尽量避免只是使用html字符串来创建节点。因为这样做既无法保证代码的有效性,同时字符串的操作效率有极低。所以应该是用document.createElement()方法,而如果文档中存在现成的样板节点,应该是用cloneNode()方法,因为使用createElement()方法之后,你需要设置多次元素的属性,使用cloneNode()则可以减少属性的设置次数——同样如果需要创建很多元素,应该先准备一个样板节点。
  3. 定时器 如果针对的是不断运行的代码,不应该使用setTimeout,而应该是用setInterval。setTimeout每次要重新设置一个定时器

封装一个图片轮换效果

8条评论»

这个东西,每次都要写,索性把它封装起来,其实并没有完全地封装,倒是可以重复使用了~···基于jQuery,需jQuery1.1.2+版本支持~···以前用纯JS写过一个,在这里,这个其实也可以用以前我写过的一些函数来实现,但是有jQuery就偷下懒了~···呵呵~

添加删除内容只需更新scripts文件夹下ap.js文件中的adList 对象即可~···

使用之前需创建一个id为img_ad的对象,以作为容器,并为其定义宽高,可随意修改ap.css,以达到你需要的效果~···

内置两种基本效果,可通过注释相应代码进行选择 ~

效果演示

打包下载

jQuery1.2选择器

发表评论»

接前文——使用jQuery进行便捷web开发

严格来说这些东西都没有多少原创性可言,只是总结一些东西,方便自己,也顺便方便一下别人~

jQuery的选择器是极其强大并且有趣的,他结合了CSS1,CSS2,部分CSS3以及部分XPath的语法,同时并有一些专有的扩展 ,这样,使用起来便得心应手。

最基本的选择器

  • #id 通过id获取对象你就可以这样写了$(“#id”),而不用再getElementById(“id”),当然实际上,很多人都在自己定义$的getElementById方法;
  • #.class 通过class获取对象,javascript中是没有专门的类似函数的
  • element 类似于getElementsByTagName
  • * 用于匹配所有元素
  • 组合选择器 直接将CSS中组合选择器的思想引用过来,各选择器之间以逗号区分,如:$(“#id,.class,h1″)

层级选择器

  • $(“parent children”) 匹配给定祖先元素下的所有后代元素,如:$(“form input”)将匹配所有表单元素中的input元素
  • parent > child 匹配给定祖先元素下的子元素,而非所有后代元素
  • prev + next 匹配一个有效选择器pre后紧接着的第一个选择器
  • prev ~ siblings 匹配一个有效选择器pre后的所有同级选择器

基本滤镜

  • :first 匹配返回对象中的第一个元素,如:$(“div:first”)将返回DOM树中的第一个div
  • :last 匹配返回对象中的最后一个元素
  • :not 去除所有与给定选择器匹配的元素,如:$(“div:not(‘.post’)”)将返回class部位“post”的所有div元素
  • :even 匹配所有索引值为偶数的元素,从 0 开始计数,这个选择器在制作“斑马线”是十分有效,如:$(“td:even”).css(“backgroundColor”,”#FFF”)
  • :odd 匹配所有索引值为奇数的元素
  • :eq(index) 匹配一个给定索引值的元素,如:$(“p:eq(0)”)将返回文档中的第一个文本段落
  • :gt(index) 匹配所有大于给定索引值的元素
  • :lt(index) 匹配所有小于给定索引值的元素
  • :header 匹配如 h1, h2, h3之类的标题元素
  • :animated 匹配所有正在执行动画效果的元素,如:$(“div:not(:animated)”)

子元素滤镜

  • :nth-child(index/even/odd/equation) 匹配其父元素下的第N个子或奇偶元素

    ‘:eq(index)’ 只匹配一个元素,而这个将为每一个父元素匹配子元素。:nth-child从1开始的,而:eq()是从0算起的!可以使用
    :nth-child(even)
    :nth-child(odd)
    :nth-child(3n)
    :nth-child(2)
    :nth-child(3n+1)
    :nth-child(3n+2)
    如:$(“ul li:noth-child(2)”)将匹配所有ul下的第二个li元素

  • :first-child 匹配第一个子元素,如$(“ul li:first-child”)将匹配ul的第一个li元素
  • last-child 匹配最后一个子元素
  • only-child 当该元素为其父元素的唯一子元素时将被匹配

属性滤镜

  • [attribute] 匹配包含特定属性的元素,如:$(“img[title]“)将匹配所有拥有title属性呃img元素
  • [attribute=value] 匹配特定属性为特定值的元素,如:$(“img[title='点击查看原图']“)匹配所有title属性为“点击查看原图”的img元素
  • [attribute^=value] 匹配特定属性其值以特定字符为起始值的元素,如:$(“img[title^='点击']“)匹配所有title属性以“点击”开始的img元素
  • [attribute$=value] 匹配特定属性其值以特定字符结尾的元素
  • [attribute*=value] 匹配特定属性其值包含特定字符的元素
  • 复合属性选择器 如:$(“img[title^='点击'][title$='原图']“)

表单滤镜

  • :input 匹配所有 input, textarea, select 和 button 元素,如:$(:input)
  • :text 匹配所有的单行文本框
  • :password 匹配密码域
  • :radio 匹配单选按钮
  • :checkbox 匹配复选框
  • :sumbit 匹配提交按钮
  • :image 匹配图像域
  • :reset 匹配重置按钮
  • :buttom 匹配按钮
  • :file 匹配文件域
  • :enabled 匹配所有可用的元素
  • :disabled 匹配所有禁用的元素
  • :checked 匹配所有被选中的表单
  • :selected 匹配所有选择的表单
  • :hidden 匹配所有不可见元素,或者type为hidden的元素

其他滤镜

  • :contains(text) 匹配包含给定文本的元素,如:$(“p:contains(‘jQuery’)”)将匹配包含”jQuery”的所有段落元素
  • :empty 匹配所有不包含子元素或者文本的空元素
  • :has 匹配所有不包含子元素或者文本的空元素,如:$(“div:has(‘p’)”)将匹配所有包含有段落元素的div元素
  • :parent 匹配含有子元素或者文本的元素
  • :visible 匹配所有的可见元素

本文相关链接: