手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表分类:Javascript

仅用 []()+! 就足以实现几乎任意Javascript代码

这篇文章很强悍,看到的时候我很惊讶,传说中的大吃一斤又出现了。
没办法,人啊。。。总是会想到奇怪的方法,呵呵。。
看内容吧。不多说了,很彪悍。

G Reader里Dexter同学的分享,来自sla.ckers.org的又一神作:点我测试

GReader里看不到效果的同学请自行测试下列HTML:

JavaScript代码
  1. <script language="javascript" type="text/javascript">  
  2. ([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]])([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]]((![]+[])[+!+[]]+(+[![]]+[])[+[]])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[+[]]+[][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()+[])[!+[]+!+[]]]((![]+[])[+!+[]]+(+[![]]+[])[+[]])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])  
  3. </script> 
在线转换工具

 

跟Brainfuck有的一拼。。。是挂马的好办法。。。

更新:研究了一下它实现的原理,有一个码表:

XML/HTML代码
  1.     (NaN+[]["filter"])[11]',  
  2. !   window["atob"]("If")[0]',  
  3. "   ("").fontcolor()[12]',  
  4. #   window["atob"]("0iN")[1]',  
  5. $   window["atob"]("0iT")[1]',  
  6. %   window["atob"]("0iW")[1]',  
  7. &   window["atob"]("0ia")[1]',  
  8. '   window["atob"]("0if")[1]',  
  9. (   (false+[]["filter"])[20]',  
  10. )   (false+[]["filter"])[21]',  
  11. *   window["atob"]("0ir")[1]',  
  12. +   window["atob"]("0it")[1]',  
  13. ,   window["atob"]("0iy")[1]',  
  14. -   (NaN+window["Date"]())[31]',  
  15. .   window["atob"]("1i4")[1]',  
  16. /   (true+("")["sub"]())[10]',  
  17. 0-9 ignored*/ ,,,,,,,,,,  
  18. :   window["Date"]()[21]',  
  19. ;   window["atob"]("O0")[0]',  
  20. <   ("")["sub"]()[0]',  
  21. =   ("").fontcolor()[11]',  
  22. >   ("")["sub"]()[10]',  
  23. ?   window["atob"]("0j9")[1]',  
  24. @   window["atob"]("00A")[1]',  
  25. A   (+[]+[]["constructor"])[10]',  
  26. B   (+[]+(false)["constructor"])[10]',  
  27. C   window["atob"]("00N")[1]',  
  28. D   window["btoa"](00)[1]',  
  29. E   window["btoa"](01)[2]',  
  30. F   (0+[]["filter"]["constructor"])[10]',  
  31. G   window["btoa"]("0f")[1]',  
  32. H   window["btoa"]("0t")[1]',  
  33. I   ("Infinity")[0]',  
  34. J   window["atob"]("00r")[1]',  
  35. K   window["btoa"]("(")[0]',  
  36. L   window["btoa"]("/")[0]',  
  37. M   window["btoa"](0)[0]',  
  38. N   ("NaN")[0]',  
  39. O   window["btoa"](8)[0]',  
  40. P   window["btoa"]("<")[0]',  
  41. Q   window["btoa"]("a")[1]',  
  42. R   window["atob"]("01I")[1]',  
  43. S   window["btoa"]("I")[0]',  
  44. T   window["btoa"]("N")[0]',  
  45. U   window["atob"]("01W")[1]',  
  46. V   window["atob"]("01a")[1]',  
  47. W   (true+window)[12]',  
  48. X   window["atob"]("01i")[1]',  
  49. Y   window["btoa"]("a")[0]',  
  50. Z   window["btoa"]("f")[0]',  
  51. [   (undefined+[]["filter"])[33]',  
  52. \   window["atob"]("01y")[1]',  
  53. ]   (true+[]["filter"])[40]',  
  54. ^   window["atob"](014)[1]',  
  55. _   window["atob"](018)[1]',  
  56. `   window["atob"]("02A")[1]',  
  57. a   ("false")[1]',  
  58. b   (window+[])[2]',  
  59. c   ([]["filter"]+[])[3]',  
  60. d   ("undefined")[2]',  
  61. e   ("true")[3]',  
  62. f   ("false")[0]',   
  63. g   ([]+("")["constructor"])[14]',  
  64. h   window["atob"]("aN")[0]',  
  65. i   ([false]+undefined)[10]',  
  66. j   (window+[])[3]',  
  67. k   window["atob"]("a0")[0]',  
  68. l   ("false")[2]',  
  69. m   (Number+[])[11]',  
  70. n   ("undefined")[1]',  
  71. o   (true+[]["filter"])[10]',  
  72. p   window["atob"]("cN")[0]',  
  73. q   window["atob"]("cf")[0]',  
  74. r   ("true")[1]',  
  75. s   ("false")[3]',  
  76. t   ("true")[0]',  
  77. u   ("undefined")[0]',  
  78. v   (0+[]["filter"])[30]',  
  79. w   ([]["sort"]["call"]()+[])[13]',  
  80. x   window["atob"]("eN")[0]',  
  81. y   (NaN+[Infinity])[10]',  
  82. z   window["atob"]("et")[0]',  
  83. {   (NaN+[]["filter"])[21]',  
  84. |   window["atob"]("03y")[1]',  
  85. }   (NaN+[]["filter"])[41]',  
  86. ~   window["atob"](234)[1]'  
拼接出来字符串 "eval",如何把 "eval" 变成 eval() 呢?方法是:[]["sort"]["call"]()["eval"]

其中 []["sort"]["call"]() 等于 [].sort.call() ,等价于 window,所以上面 []["sort"]["call"]()["eval"] 就等价于 window.eval

然后就是体力活了,把码表对应转换成 eval("blah blah") 这种形式就可以执行任意代码了,不同浏览器的码表不一样。 Chrome和Firefox的index就不一样。

其实这个码表还可以通过 ·toLocal*()` 函数族扩展到Unicode,比fromCharCode要简短 :D

原文来自:http://www.cnblogs.com/pandora/archive/2010/02/27/1674833.html

 

JavaScript单元测试工具 — QUnit

好象这篇文章的原始链接来自cssrain,不记得了。。如果作者看到,请联系我一下,我加上链接,SORRY了。

文章来自google doc,内容如下:

QUnit是jQuery团队开发的 JavaScript单元测试工具,使用方便,界面美观。近期试用了一下并进一步了解了JavaScript单元测试,记录一下所思所得。

什么是单元测试

XML/HTML代码
  1. 单元测试又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。单元测试主要是用来检验程式的内部逻辑,也称为个体测试、结构测试或逻辑驱动测试。通常由撰写程式码的程式设计师负责进行。  
  2.   
  3. 通常来说,程式設計師每修改一次程式就會進行最少一次單元測試,在編寫程式的過程中前後很可能要進行多次單元測試,以證實程式達到軟件規格書 (en:Specification)要求的工作目標,沒有臭蟲;雖然单元测试不是什么必须的,但也不坏,這牽涉到專案管理的政策決定。  
  4.   
  5. —— 维基百科 (中文英文)  

 

为什么 JavaScript需要单元测试

由于存在浏览器解析环境、用户操作习惯等差异,前端程序的许多问题是无法捕捉或重现的,现在前端程序的测试多是黑盒测试,即靠点击点击点击来寻找程序bug。这种方式既费时费力,又无法保证测试的覆盖面。

同时,前端逻辑和交互越来越复杂,和其他编程语言一样,一 个函数,一个模块,在修改bug或添加新功能的过程中,很容易就产生新的bug,或使老的bug复活。这种情况下,反复进行黑盒测试,其工作量和测试质量 是可想而知的。

此外,浏览器兼容性测试是前 端程序测试的重要一环,在多个浏览器之间测试前端程序,上面说的工作量就会成n倍的增加。

为什么我们的前端程序如此脆弱?就是因为没用单元测试。。

假如使用了单元测试,上边的问题就变得很容易了,当然前提 是你要花时间去研究和编写测试用例。

根据函 数或模块的源代码,编写出包含各种情况的测试用例,每次解决bug或添加新功能,都随时更新这个用例然后进行测试,很容易就找出新bug和“复活”的老 bug。

测试兼容性,只需要在不同的浏览器 中分别运行这个测试,问题就一目了然了。

也 许白盒比黑盒要多费几倍的脑子,但想想我们那脆弱的程序,想想那些随时冒出来的烦人的老bug,费点脑子,值了!

使用QUnit

注:下面的内容主要参考了 QUnit文档 和 NetTuts+的这篇文章

建立一个测试页面,引入 qunit.js 和 qunit.css 这 两个必需的文件,这两个文件是存放在github上的,鉴于目前操蛋的互联网环境,最好下载到本地调用。

注:body中的元素id命名必须依照如下形式,否则无法 正常显示。

XML/HTML代码
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  2. <html>  
  3. <head>  
  4.   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  5.   <link rel="stylesheet"href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css"media="screen" />  
  6.   <script type="text/javascript"src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>  
  7. </head>  
  8. <body>  
  9.   <h1 id="qunit-header">QUnit example</h1>  
  10.   <h2 id="qunit-banner"></h2>  
  11.   <h2 id="qunit-userAgent"></h2>  
  12.   <ol id="qunit-tests"></ol>  
  13. </body>  
  14. </html>  

测试示例

下面是一个最简单的函数测试用例,解释请见程序注释。

JavaScript代码
  1. //定义测试模块  
  2. module( "测试示例" );  
  3. //定义一个简单的函数,判断参数是不是数字  
  4. function simpleTest(para) {  
  5.   if(typeof para == "number") {  
  6.     return true;  
  7.   }  
  8.   else{  
  9.     return false;  
  10.   }  
  11. }  
  12. //开始单元测试  
  13. test('simpleTest()'function() {  
  14.   //列举各种可能的情况,注意使用 ! 保证表达式符合应该的逻辑  
  15.   ok(simpleTest(2), '2 是一个数字');  
  16.   ok(!simpleTest("2"), '"2"不是一个数字');  
  17. });  

module( name, [lifecycle] ) 函数指定测试模块和周期。

ok( state, [message] ) 是QUnit中最常用的一个判断函数,只能判断true和false。

DEMO在这里,看一下测试结果:

大小: 19.15 K
尺寸: 326 x 221
浏览: 1769 次
点击打开新窗口浏览全图

结果都是绿的,说明两条测试语句都符合设定的规则。可以尝试修改下规则

JavaScript代码
  1. //...  
  2. ok(simpleTest("2"), '"2"是一个数字');  
  3. //...  

就可以看到爆红了。。

更多测试判断

除了ok()之外,QUnit还有如下几个判断函数:

相等判断equals( actual, expected, [message] )

示例:

JavaScript代码
  1. //定义一个简单的函数,返回数字和2的乘积  
  2. function simpleTest1(para) {  
  3.   return para * 2;  
  4. }  
  5. //开始单元测试  
  6. test('simpleTest1()'function() {  
  7.   //列举各种可能的情况  
  8.   equals(simpleTest1(2), 4, '2 * 2 等于 4');  
  9.   equals(simpleTest(2), 3, '2 * 2 等于 3');  
  10. });  

 

相同判断 (包含数组、对象等)same( actual, expected, [message] )

示例:

JavaScript代码
  1. //定义一个简单的函数,返回一个数组  
  2. function simpleTest2() {  
  3.   return [1, 2];  
  4. }  
  5. //开始单元测试  
  6. test('simpleTest2()'function() {  
  7.   //列举各种可能的情况  
  8.   equals(simpleTest2(), [1, 2], '函数返回数组[1, 2]');  
  9.   equals(simpleTest2(), [1, 1], '函数返回数组[1, 1]');  
  10. });  

same()和意思和equals()差不多,但 same()可以判断数组、对象等的相同,而equals不能。

异步与Ajax

对于异步程序的测试,如setTimeout、 setInterval、Ajax等情况,按照上面的方法,在异步调用执行之前,测试就已完成并输出了结果。这时,配合使用QUnit提供的两个函数:stop( [timeout] ) 和 start(),也可以轻松搞定。

直接看例子:

JavaScript代码
  1. //异步测试  
  2. module( "异步测试示例" );  
  3. //setTimeout  
  4. test('asynchronous test'function() {  
  5.   // 暂停测试  
  6.   stop();  
  7.    
  8.   setTimeout(function() {  
  9.     ok(true'完成运行');  
  10.     //待测试完成后,恢复  
  11.     start();  
  12.   }, 100)  
  13. })  
  14. //另一种形式  
  15. asyncTest('asynchronous test'function() {  
  16.   setTimeout(function() {  
  17.     ok(true);  
  18.     //待测试完成后,恢复  
  19.     start();  
  20.   }, 100)  
  21. })  
Ajax也是类似的道理:
JavaScript代码
  1. //Ajax测试  
  2. function ajax(successCallback) {  
  3.   $.ajax({  
  4.     url: 'server.php',  
  5.     success: successCallback  
  6.   });  
  7. }  
  8.    
  9. test('asynchronous test'function() {  
  10.   // 暂停测试  
  11.   stop();  
  12.    
  13.   ajax(function() {  
  14.     // 异步调用判断  
  15.   })  
  16.    
  17.   setTimeout(function() {  
  18.     //异步测试完成后,恢复  
  19.     start();  
  20.   }, 2000);  
  21. })  

了解更多

 

 

Tags: 单元测试, qunit

【转】jQuery性能规则

转载的关于jQuery性能设置的文章 。。。

 之前,我们需要担心减少字节数和请求次数以及加载顺序以使页面加载的更快。如今,我们越来越多的注意到一个影响性能的重要组成部分--CPU利用 率。使用 jQuery和其他JavaScript框架,使节点选择和DOM操作变得越来越容易,但如果你不小心使用了一些减少浏览器本身要做的工作的一些做法可能 会带来不好的结果。

  1. 总是使用#id去寻找element
  2. 在Classes前面使用Tags
  3. 缓存jQuery对象
  4. 更好的利用链
  5. 使用子查询
  6. 限制直接对DOM操作
  7. 事件委托(又名:冒泡事件)
  8. 消除查询浪费
  9. 遵从 $(window).load
  10. 压缩JS
  11. 学习jQuery库

1.总是使用#id去寻找element.

 在jQuery中最快的选择器是ID选择器 ($('#someid')). 这是因为它直接映射为JavaScript的getElementById()方法。

选择单个元素

XML/HTML代码
  1. <div id="content">  
  2.     <form method="post" action="/">  
  3.         <h2>Traffic Light</h2>  
  4.         <ul id="traffic_light">  
  5.             <li><input type="radio" class="on" name="light" value="red" /> Red</li>  
  6.             <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>  
  7.             <li><input type="radio" class="off" name="light" value="green" /> Green</li>  
  8.         </ul>  
  9.         <input class="button" id="traffic_button" type="submit" value="Go" />  
  10.     </form>  
  11. </div>  

选择button的性能不好的一种方式:
var traffic_button = $('#content .button');

取而代之的是直接选择button:
var traffic_button = $('#traffic_button');

选择多个元素

在我们讨论选择多个元素的时候,我们真正需要知道的是DOM的遍历和循环才是性能低下的原因。为了尽量减少性能损失, 总是使用最近的父ID去寻找。
var traffic_lights = $('#traffic_light input');

2.在Classes前面使用Tags

在jQuery中第二快的选择器就是Tag选择器 ($('head')). 而这是因为它直接映射到JavaScript的getElementsByTagName()方法。

XML/HTML代码
  1. <div id="content">  
  2.     <form method="post" action="/">  
  3.         <h2>Traffic Light</h2>  
  4.         <ul id="traffic_light">  
  5.             <li><input type="radio" class="on" name="light" value="red" /> Red</li>  
  6.             <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>  
  7.             <li><input type="radio" class="off" name="light" value="green" /> Green</li>  
  8.         </ul>  
  9.         <input class="button" id="traffic_button" type="submit" value="Go" />  
  10.     </form>  
  11. </div>  

总是在一个Class前面加上一个tag名字(记得从一个ID传下来)
var active_light = $('#traffic_light input.on');

注意:在jQuery里Class选择器是最慢的一个选择器;在IE中它循环整个DOM。可能的话尽量避免使用它。不要在ID前面加Tags。例如,它会因为去循环所有的<div>元素去寻找ID为content的<div>,而导致很慢。
var content = $('div#content');

按照同样的思路,从多个ID传下来是冗余的。
var traffic_light = $('#content #traffic_light');

3.缓存jQuery对象

养成保存jQuery对象到一个变量上(就像上面的例子)的习惯。例如,不要这样做:

JavaScript代码
  1. $('#traffic_light input.on).bind('click', function(){...}); 
  2. $('#traffic_light input.on).css('border''3px dashed yellow');  
  3. $('#traffic_light input.on).css('background-color', 'orange'); 
  4. $('#traffic_light input.on).fadeIn('slow');  

取而代之,首现保存jQuery变量到一个本地变量后,再继续你的操作。

JavaScript代码
  1. var $active_light = $('#traffic_light input.on');  
  2. $active_light.bind('click'function(){...});  
  3. $active_light.css('border''3px dashed yellow');  
  4. $active_light.css('background-color''orange');  
  5. $active_light.fadeIn('slow');  

提示:使用$前辍表示我们的本地变量是一个jQuery包集。记住,不要在你的应该程序里出现一次以上的jQuery重复的选择操作。

 额外提示:延迟存储jQuery对象结果。

如果你想在你的程序的其它地方使用jQuery结果对象(result object(s)),或者你的函数要执行多次,要把它缓存在一个全局范围的对象里。通过定义一个全局容器保存jQuery结果对象,就可以在其它的函数里引用它。

JavaScript代码
  1. // Define an object in the global scope (i.e. the window object)  
  2. window.$my =  
  3. {  
  4.     // Initialize all the queries you want to use more than once  
  5.     head : $('head'),  
  6.     traffic_light : $('#traffic_light'),  
  7.     traffic_button : $('#traffic_button')  
  8. };  
  9.   
  10. function do_something()  
  11. {  
  12.     // Now you can reference the stored results and manipulate them  
  13.     var script = document.createElement('script');  
  14.     $my.head.append(script);  
  15.   
  16.     // When working inside functions, continue to save jQuery results  
  17.     // to your global container.  
  18.     $my.cool_results = $('#some_ul li');  
  19.     $my.other_results = $('#some_table td');  
  20.   
  21.     // Use the global functions as you would a normal jQuery result  
  22.     $my.other_results.css('border-color''red');  
  23.     $my.traffic_light.css('border-color''green');  
  24. }  

4.更好的利用链

 前面的例子也可以这样写:

JavaScript代码
  1. var $active_light = $('#traffic_light input.on');$active_light.bind('click'function(){...})  
  2.     .css('border''3px dashed yellow')  
  3.     .css('background-color''orange')  
  4.     .fadeIn('slow');  

这样可以让我们写更少的代码,使JavaScript更轻量。

5.使用子查询

jQuery允许我们在一个包集上附加其它的选择器。因为我们已经在本地变量里保存了父对象这样会减少以后在选择器上的性能开销。

XML/HTML代码
  1. <div id="content">  
  2.     <form method="post" action="/">  
  3.         <h2>Traffic Light</h2>  
  4.         <ul id="traffic_light">  
  5.             <li><input type="radio" class="on" name="light" value="red" /> Red</li>  
  6.             <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>  
  7.             <li><input type="radio" class="off" name="light" value="green" /> Green</li>  
  8.         </ul>  
  9.         <input class="button" id="traffic_button" type="submit" value="Go" />  
  10.     </form>  
  11. </div>  

例如,我们可以利用子查询缓存active和inactive lights以便后面的操作。

JavaScript代码
  1. var $traffic_light = $('#traffic_light'),  
  2.     $active_light = $traffic_light.find('input.on'),  
  3.     $inactive_lights = $traffic_light.find('input.off');  

提示:可以用逗号隔开一次定义多个本地变量,这样可以节省一些字节。

 6.限制直接对DOM操作

DOM操作的基本做法是在内存中创建DOM结构,然后再更新DOM结构。这不是jQuery最好的做法,但对JavaScript来讲是高效的。直接操作DOM结构性能是低下的。 例如,如果你需要动态创建一列元素,不要这样做:

JavaScript代码
  1. var top_100_list = [...], // assume this has 100 unique strings  
  2.     $mylist = $('#mylist'); // jQuery selects our <ul> element  
  3.   
  4. for (var i=0, l=top_100_list.length; i<l; i++)  
  5. {  
  6.     $mylist.append('<li>' + top_100_list[i] + '</li>');  
  7. }  

取而代之,我们希望在插入DOM结构之前先在一个字符串里创建一套元素。

JavaScript代码
  1. var top_100_list = [...], // assume this has 100 unique strings  
  2.     $mylist = $('#mylist'), // jQuery selects our <ul> element  
  3.     top_100_li = ""// This will store our list items  
  4.   
  5. for (var i=0, l=top_100_list.length; i<l; i++)  
  6. {  
  7.     top_100_li += '<li>' + top_100_list[i] + '</li>';  
  8. }  
  9. $mylist.html(top_100_li);  

更快的做法,在插入DOM结构之前我们应该总是在一个父节点里包含许多元素

JavaScript代码
  1. var top_100_list = [...], // assume this has 100 unique strings  
  2.     $mylist = $('#mylist'), // jQuery selects our <ul> element  
  3.     top_100_ul = '<ul id="#mylist">'// This will store our entire unordered list  
  4.   
  5. for (var i=0, l=top_100_list.length; i<l; i++)  
  6. {  
  7.     top_100_ul += '<li>' + top_100_list[i] + '</li>';  
  8. }  
  9. top_100_ul += '</ul>'// Close our unordered list  
  10.   
  11. $mylist.replaceWith(top_100_ul);  

如是你照着上面的做了还是对性能有些迷惑的话,可以参考以下内容:

7. 事件委托(又名:冒泡事件)

除非特别说明,每一个JavaScript事件(如click, mouseover 等)在DOM结构树上都会冒泡到它的父元素上。如果我们想让很多elements(nodes)调用同一个function这是非常有用的。取而代之的是 你可以只对它们的父级绑定一次,而且可以计算出是哪一个节点触发了事件,而不是绑定一个事件监听器到很多节点上这种效率低下的方式。例如,假如我们要开发 一个包含很多input的大型form,当input被选择的时候我们想绑定一个class name。像这样的帮定是效率低下的:

XML/HTML代码
  1. $('#myList li).bind('click', function(){  
  2.     $(this).addClass('clicked');  
  3.     // do stuff  
  4. });  

 

反而,我们应该在父级侦听click事件。

JavaScript代码
  1. $('#myList).bind('click', function(e){ 
  2.     var target = e.target, // e.target grabs the node that triggered the event. 
  3.         $target = $(target);  // wraps the node in a jQuery object 
  4.     if (target.nodeName === 'LI') {  
  5.         $target.addClass('clicked');  
  6.         // do stuff  
  7.     }  
  8. });  

父节点担当着发报机的工作,可以在触发了事件的目标element上做一些工作。如果你发现自己把一个event listener帮定到很多个element上,那么你这种做法是不正确的。

 8.消除查询浪费

虽然jQuery对没有找到任何匹配的elements处理的很好,但是它还是需要花费时间去查找的。如果你的站点有一个全局的JavaScript,你可能会把每个jQuery function都放在 $(document).ready(function(){ // all my glorious code })里。 不要这样做。只去放一些页面上适合用到的function。这样做最有效的方式是你的模板可以完全控制任何时候或者地方执行JavaScript以内联脚 本的方式初始化function。例如,在你的“article”页面模板里,你可能在body标签关闭之前包含以下代码

XML/HTML代码
  1. <script type="text/javascript>  
  2. mylib.article.init();  
  3. </script>  
  4. </body>  

如果你的页面模板包含多种有可能在页面或者不在页面上的模块,或者为了可视化效果你需要它们稍后再初如化,你应该在这些模块之后立即放置初如化函数。

XML/HTML代码
  1. <ul id="traffic_light">  
  2.     <li><input type="radio" class="on" name="light" value="red" /> Red</li>  
  3.     <li><input type="radio" class="off" name="light" value="yellow" /> Yellow</li>  
  4.     <li><input type="radio" class="off" name="light" value="green" /> Green</li>  
  5. </ul>  
  6. <script type="text/javascript>  
  7. mylib.traffic_light.init();  
  8. </script>  
你的全局JavaScript库看起来应该是这样的:
JavaScript代码
  1. var mylib =  
  2. {  
  3.     article_page :  
  4.     {  
  5.         init : function()  
  6.         {  
  7.             // Article page specific jQuery functions.  
  8.         }  
  9.     },  
  10.     traffic_light :  
  11.     {  
  12.         init : function()  
  13.         {  
  14.             // Traffic light specific jQuery functions.  
  15.         }  
  16.     }  
  17. }  

9 遵从$(windows).load

有一种诱惑会使jQuery开发者hook所有事情到 $(document).ready 这个虚伪的事件里。毕竟在大多数例子里都可以看到这样使用。虽然$(document).ready 非常有用,它在页面呈现时发生,虽然其它对象还在下载中。如果你发现你的页面在下载中停顿,就有可能是$(document).ready 引起的。你可以通过把jQuery functions帮定到$(window).load事件来减少下面下载时的CPU使用率,它是在所有HTML(包括iframe内容)都下载完以后才去调用所有对象的。

$(window).load(function(){
    
// jQuery functions to initialize after the page has loaded.
});

多余的功能,如拖拽、帮定可视化效果和动画、预读取图片等,使用这种方法比较好。

10 压缩JS

虽然和jQuery无关,但在这里也要提一下。使JavaScript函数和变量变得可读是一个趋势,这对开发者来讲是必不可少的,但对普通用户来 讲没有任何关系。不用什么借口,是时候把JS压缩纳入我们的工作流程中来了。注释你的代码,在投放到生产环境之前找一个压缩工具进行压缩。使用YUICompressor 压缩你代码中多余的浪费的字节。根据我们的经验,它可以安全的把JavaScript压缩的尽可能小,而不会多占用CPU。小提示:为了在YUICompressor里最大化压缩,应该这样这样定义变量(例如:var my_long_variable_name;)

11 学习jQuery库

学习jQuery最好的方法就是去查jQuery的文档了,可以当作手册来用。

本文来自博客园,作者是Skyline.xin,来源网址是:http://www.cnblogs.com/trendline/archive/2010/02/05/jquery-performance-rules.html,用他的话来说,他是翻译:http://www.artzstudio.com/2009/04/jquery-performance-rules/,可惜我的英文太差。否则我也可以翻译啥的了。。

感谢翻译者为我们带来的快乐。

jQuery操作select

jQuery这个框架方便了我们对于HTML元素的操作,本来以为自己对于Select操作也算是熟悉了,但上午在测试的时候才发现自己了解的还真不多。

看了一下jQuery的一些方法后,理出了一些常用的方法,列在下面:

JavaScript代码
  1. //获取第一个option的值  
  2. $('#test option:first').val();  
  3. //最后一个option的值   
  4. $('#test option:last').val();  
  5. //获取第二个option的值  
  6. $('#test option:eq(1)').val();  
  7. //获取选中的值  
  8. $('#test').val();  
  9. $('#test option:selected').val();  
  10. //设置值为2的option为选中状态  
  11. $('#test').attr('value','2');  
  12. //设置第一个option为选中  
  13. $('#test option:last').attr('selected','selected');  
  14. $("#test").attr('value' , $('#test option:last').val());  
  15. $("#test").attr('value' , $('#test option').eq($('#test option').length - 1).val());  
  16. //获取select的长度  
  17. $('#test option').length;  
  18. //添加一个option  
  19. $("#test").append("<option value='9'>ff</option>");  
  20. $("<option value='9'>ff</option>").appendTo("#test");  
  21. //添除选中项  
  22. $('#test option:selected').remove();  
  23. //指定项选中  
  24. $('#test option:first').remove();  
  25. //指定值被删除  
  26. $('#test option').each(function(){  
  27.     if( $(this).val() == '5'){  
  28.         $(this).remove();  
  29.     }  
  30. });  
  31. $('#test option[value=5]').remove();  
  32.   
  33. //获取第一个Group的标签  
  34. $('#test optgroup:eq(0)').attr('label');  
  35. //获取第二group下面第一个option的值   
  36. $('#test optgroup:eq(1) :option:eq(0)').val();  

 

 想来应该够用了吧?呵呵

 

Tags: jquery, select

孟宪会之AJAX(XMLHttpRequest)进行跨域请求方法详解

跨域请求,顾名思义,就是一个站点中的资源去访问另外一个不同域名站点上的资源。这种情况很常见,比如说通过 style 标签加载外部样式表文件、通过 img 标签加载外部图片、通过 script 标签加载外部脚本文件、通过 Webfont 加载字体文件等等。默认情况下,脚本访问文档属性等数据采用的是同源策略(Same origin policy)。

那么,什么是同源策略呢?如果两个页面的协议、域名和端口是完全相同的,那么它们就是同源的。同源策略是为了防止从一个地址加载的文档或脚本访问或者设置 从另外一个地址加载的文档的属性。如果两个页面的主域名相同,则还可以通过设置 document.domain 属性将它们认为是同源的。

随着 Web2.0 和 SNS 的兴起,Web 应用对跨域访问的需求也越来越多,但是,在脚本中进行跨域请求是受安全性限制的,Web 开发人员迫切需要提供一种更安全、方便的跨域请求方式来融合(Mashup)自己的 Web 应用。这样做的一个好处就是可以将请求分摊到不同的服务器,减轻单个服务器压力以提高响应速度;另外一个好处是可以将不同的业务逻辑分布到不同的服务器上 以降低负载。

值得庆幸的是,跨域请求的标准已经出台,主流浏览器也已经实现了这一标准。W3C 工作组中的 Web Applications Working Group(Web 应用工作组)发布了一个 Cross-Origin Resource Sharing(跨域资源共享,该规范地址:http://www.w3.org/TR/access-control/和http: //dev.w3.org/2006/waf/access-control/) 推荐规范来解决跨域请求的问题。该规范提供了一种更安全的跨域数据交换方法。具体规范的介绍可以访问上面提供的网站地址。值得注意的是:该规范只能应用在 类似 XMLHttprequest 这样的 API 容器内。IE8、Firefox 3.5 及其以后的版本、Chrome浏览器、Safari 4 等已经实现了 Cross-Origin Resource Sharing 规范,已经可以进行跨域请求了。

Cross-Origin Resource Sharing 的工作方式是通过添加 HTTP 头的方法来判断哪些资源允许 Web 浏览器访问该域名下的信息。然而,对于那些 HTTP 请求导致用户数据产生副作用的请求方法(特别是对于除了GET、某些 MIME 类型的 POST 之外的 HTTP方法),该规范要求浏览器对请求进行“预先验”,通过发送 HTTP 的 OPTIONS 请求头询问服务器有哪些支持的方法,在征得服务器的同意后,再使用实际的 HTTP 请求方法发送实际的请求。服务器也可以通知客户端是否需要将验证信息(如 Cookie 和 HTTP Authentication 数据)随同请求一起发送。

请看详细。。。

» 阅读全文