让你的浏览器动起来的js代码解析
网上看到的一段很好玩的js代码,感觉写得很精妙,值得收藏。
想让你的浏览器里的图片转起来了,直接在地址栏内输入如下:
javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6;
y3=.24; x4=300; y4=200; x5=300; y5=200;
DI=document.getElementsByTagName("img"); DIL=DI.length;
function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style;
DIS.position='absolute'; DIS.left=(Math.sin(R*x1+i*x2+x3)*x4+x5)+"px";
DIS.top=(Math.cos(R*y1+i*y2+y3)*y4+y5)+"px"}R++}setInterval('A()',5);
void(0);
想让你的浏览器晃起来么,直接在地址栏内输入如下:
javascript:function shake_xy(n) {if (self.moveBy)
{for (i = 10; i > 0; i--)
{for (j = n; j > 0; j--) {self.moveBy(0,i);self.moveBy(i,0);
self.moveBy(0,-i);self.moveBy(-i,0);}}}}
setInterval('shake_xy(5)',5); void(0);
我们来整理一番,分析下这段华丽的代码是怎么做到的。
深入解析
R = 0;
x1 = .1;
y1 = .05;
x2 = .25;
y2 = .24;
x3 = 1.6;
y3 = .24;
x4 = 300;
y4 = 200;
x5 = 300;
y5 = 200;
DI = document.images;
DIL = DI.length;
function A(){
for (i = 0; i - DIL; i++) {
DIS = DI[i].style;
DIS.position = 'absolute';
DIS.left = Math.sin(R * x1 + i * x2 + x3) * x4 + x5;
DIS.top = Math.cos(R * y1 + i * y2 + y3) * y4 + y5
}
R++
}
setInterval('A()', 5);
void (0);
其实原理上来说不难,就是将文档中的图片的style属性,位置设置成absolute,然后让left跟top做曲线运动。5ms执行一次变化。
这个源代码的作者确实很赞的说,很好很强大。
这里面有一些技巧性的东西,比如0.x直接简写成.x,for循环里面用i-DIL,利用JavaScript弱类型,0等同于false,来达到与i < DIL 一样的效果
这2天偶然下了下JavaScript王者归来这本电子书,翻开一看,惊奇的发现前面几个部分就是详细的分析了这个函数,让我们来看看JavaScript王者归来的作者是怎么分析的吧。
首先,一些浏览器(不是所有的)支持JavaScript伪协议,你可以在浏览器的地址栏里通过“JavaScript:”的形式来执行JavaScript代码。实际上这种良好的执行方式为JavaScript爱好者带来了一个便捷的测试手段,使得他们能够以类似命令行的方式来简易地测试一个没有用过的JavaScript特性,而不必写一大堆文本和HTML标签。
其次,JavaScript支持缺省声明直接赋值的方式来使用全局变量,唯一的约束是命名规则和保留字,作为一种脚本语言,这个特性无疑提供了一种快速便利的执行手段,缺点则也是很明显的,缺乏严谨的约束,为不良代码的产生提供了可能。
注意到document.images的用法,这个指令枚举出页面文档中所有的图片元素,并把这个元素集合的引用赋值给临时变量DI。
DI=document.images;
Document是一个非常有用的接口,它是JavaScript访问页面文档对象的主要方式。除了访问图片的document.images之外,document提供的属性还能够方便地引用页面文档对象中的表单、链接和其他元素。
另一个需要重点关注的特性是函数定义,function A()声明了一个名字叫做“A”的函数,其后的一对大括号内的指令是对这个函数的定义。提供函数文法使得JavaScript成为一种完善的过程式语言。
在函数定义体内,我们可以看到像Math.cos(R*x1+i*x2+x3)这样的用法,Math是JavaScript的一个有用的内置对象,它为JavaScript的使用者提供了一组有用的数学函数,Math.cos返回表达式的余弦值。
在这之后我们通过一个循环将数学计算的结果赋值给document.images集合中提供的图片样式属性,这里引用的是style.top和style.left属性,这两个属性分别定义了图片元素左上角距参照系原点的横坐标和纵坐标的值,默认的单位是像素点(关于元素的定位问题我们将会在后续的章节中有详细的讨论),这样我们相当于将页面文档中的图片元素抽取出来,重新计算了它们的位置,并按照新的位置进行排列。
最后,我们在排列的过程中改变参量R的值,并通过定时器函数setInterval每隔5个毫秒调用一次A()函数,就实现了例子中的图片旋转的特效。
setInterval(‘A()’,5);
在结束话题之前,顺便提一个不太常用的特性。也许你已经注意到例子末尾的那个不起眼的void(0),如果你将它去掉,你会发现一切令人惊讶的特效都消失了,甚至连浏览器中的页面也不见踪迹,取而代之的是孤零零地显示在浏览器窗口左上角的一组奇怪的数字,这是怎么回事呢?
原来JavaScript伪协议默认将页面带到一个新的document中并显示程序返回结果,所以正常情况下运算的结果会在一个空文档对象内显示,这样也就没有图片可以展现特效,而void(0)阻止了这个跳转动作。
void是JavaScript的一个特殊的运算符,它的作用是舍弃任何参数表达式的值,这意味着要求解析器检验并计算参数表达式内容,但是却忽略其结果。如果你刻意去检查void运算的返回值,会发现它返回一个undefined标记(事实上任何一个不带return指令的函数运算的默认返回值都是undefined)。在浏览器的缺省行为中,undefined阻止了页面的跳转。
在代码中,我们用表达式undefined;取代void(0),也能得到相同的结果。
这段代码的经典之处不但在于它实现的效果令人惊叹,还在于它在短短的几行指令中体现了客户端JavaScript中大多数重要的特性,这些特性包括我们前面提到的伪协议、全局变量、文档接口、集合对象、函数、内置对象、元素样式属性、定时器以及void()和undefined,除此以外还提到了代码中没有出现的闭包、函数实例化以及typeof操作符,这些特性几乎构成了客户端JavaScript的全部