是什么使得JavaScript不同于其他程序设计语言,在浏览器修饰方面表现出其优异的特性?毫无疑问,JavaScript在Web应用领域受到的好评,既源于它自身灵活的动态特性,也源于浏览器对它充分的支持。

JavaScript是一种深受浏览器“宠爱”的语言,浏览器为其提供了丰富的资源和广阔的舞台。

下面的这段代码在网络上广为流传,被众多JavaScript爱好者奉为代表JavaScript魔力的经典:

例1.2 神奇的“魔法代码”

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.images; DIL=DI.length; function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style; DIS.position='absolute'; DIS.left=Math.cos(R*x1+i*x2+x3)*x4+x5; DIS.top=Math.sin(R*y1+i*y2+y3)*y4+y5}R++}setInterval('A()',5); void(0);

打开一个带有几张图片的网页(图片稍微多一些并且每张图片大小相当的话,效果会比较好),将上面这段代码输入到IE浏览器的地址栏(不要换行),敲回车,就会看到页面上的所有图片围成一圈绕着一个点旋转。事实上,这是一段有些故弄玄虚的指令,很容易让初学者觉得新奇和迷惑,而对于资深的JavaScript程序员来说,它几乎恰如其分地表现出了JavaScript大部分操作客户端浏览器的特性(除了故意的糟糕排版和蹩脚的变量命名方式之外)。

在这里,我们先简要地列举一下这些特性,而具体的内容将会在后续的章节里详细展开。

首先,一些浏览器(不是所有的)支持JavaScript伪协议,你可以在浏览器的地址栏里通过“JavaScript:”的形式来执行JavaScript代码。实际上这种良好的执行方式为JavaScript爱好者带来了一个便捷的测试手段,使得他们能够以类似命令行的方式来简易地测试一个没有用过的JavaScript特性,而不必写一大堆文本和HTML标签。

其次,JavaScript支持缺省声明直接赋值的方式来使用全局变量,唯一的约束是命名规则和保留字,作为一种脚本语言,这个特性无疑提供了一种快速便利的执行手段,缺点则也是很明显的,缺乏严谨的约束,为不良代码的产生提供了可能。

大部分程序设计语言中,变量被设计为在声明之后引用,也就是说,要使用某个对象,必须先告知该对象存在之后才能赋值,即先“(在……之中)有一个A”,然后才能说“A是一个……”,在JavaScript中,如果对象的作用域是全局的,则不强制要求“有一个A”的声明。关于变量定义和声明的内容,在第4章将会有详细的讨论。

作为程序员,如果你不管理好自己代码里的变量,那么总有一天你或者你的继任会为它们整天头疼不已。可能出现在任何地方的变量,像缺乏约束四处乱窜的野马,随时都可能导致整个系统崩溃。一个好的习惯是用良好的自我约束来限制变量的定义和使用,并且避免定义过多的全局变量。在JavaScript中,利用闭包是一种代替临时变量的好习惯,在后续的章节中,我们会详细讨论这些现在听起来有些深奥的技巧。

注意到document.images的用法,这个指令枚举出页面文档中所有的图片元素,并把这个元素集合的引用赋值给临时变量DI。

DI=document.images;

Document是一个非常有用的接口,它是JavaScript访问页面文档对象的主要方式。除了访问图片的document.images之外,document提供的属性还能够方便地引用页面文档对象中的表单、链接和其他元素。

document 接口还提供了一组更为标准的方法来创建和访问文档元素,它们是document.getElementById、 document.getElementsByTagName和document.createElement,通常我们认为以上三个方法是 document对象提供的最主要的DOM接口。关于DOM话题我们将会在第12章里详细讨论。

除了Document之外,另一个有用的接口是Window,它提供了对浏览器、窗口、框架、对话框以及状态栏的访问方法,在第三部分里,我们会用很多篇幅仔细地讨论以上两个接口。

另一个需要重点关注的特性是函数定义,function A()声明了一个名字叫做“A”的函数,其后的一对大括号内的指令是对这个函数的定义。提供函数文法使得JavaScript成为一种完善的过程式语言。

function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style; DIS.position='absolute'; DIS.left=Math.cos(R*x1+i*x2+x3)*x4+x5; DIS.top=Math.sin(R*y1+i*y2+y3)*y4+y5}R++}

除了命名函数之外,JavaScript提供了缺省函数名的定义方法,在某些特定情况下,定义在函数体内部的匿名函数在执行的过程中形成“闭包”。除此以外,JavaScript还提供了一种new操作符来实例化函数对象。以上的两个特性使得JavaScript同时兼有函数式和面向对象的特点,也使得函数成为了JavaScript的第一型。在第6章、第22章、第23章我们将会分别详细讨论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);

setInterval是JavaScript中 一个重要的系统函数,它提供了一种定时执行函数的方法,另一个类似的函数是setTimeout,我们将在第16章里详细地讨论它们。在一些稍为复杂的应 用中,setInterval和setTimeout被大量用于实现动态效果、模拟异步执行、实现拦截器和一些控制型模式,以及实现自定义事件接口。

在结束话题之前,顺便提一个不太常用的特性。也许你已经注意到例子末尾的那个不起眼的void(0),如果你将它去掉,你会发现一切令人惊讶的特效都消失了,甚至连浏览器中的页面也不见踪迹,取而代之的是孤零零地显示在浏览器窗口左上角的一组奇怪的数字,这是怎么回事呢?

原来JavaScript伪协议默认将页面带到一个新的document中并显示程序返回结果,所以正常情况下运算的结果会在一个空文档对象内显示,这样也就没有图片可以展现特效,而void(0)阻止了这个跳转动作。

void是JavaScript的 一个特殊的运算符,它的作用是舍弃任何参数表达式的值,这意味着要求解析器检验并计算参数表达式内容,但是却忽略其结果。如果你刻意去检查void运算的 返回值,会发现它返回一个undefined标记(事实上任何一个不带return指令的函数运算的默认返回值都是undefined)。在浏览器的缺省 行为中,undefined阻止了页面的跳转。

undefined对于JavaScript来说是一个特殊的值,它令我想起了某些宗教和物理学。如果说程序中的null代表着“空”的话,那么undefined则代表着“无”。“空”依然是一种存在,而“无”则是存在的对立面。JavaScript的一个巧妙设计就在于把“无”概念化了,由于它没有强制检验对象存在的机制,所以它承认“无”的概念,任何一个未经定义和使用的标识,均可以用“无”来表示。这个“无”在JavaScript文法中即是undefined。

typeof 操作符用来检查变量的类型,如果你直接引用一个未声明的标识,或者声明了一个变量却未对其进行赋值,那么typeof操作返回的结果将是 undefined。事实上我觉得最好能够用一种新的标识来区分未声明和已声明未赋值的变量,如unknown(未知)区别undefined(无)。当 然JavaScript并没有这么实现。尽管如此,大多数时候拥有undefined和null,就已经足够了。

将以下各行代码分别输入到浏览器的地址栏,体会一下undefined和null的区别:

JavaScript:alert(typeof(x));

JavaScript:var x;alert(typeof(x));

JavaScript:var x=null;alert(typeof(x));

在例1.2代码中,我们用表达式undefined;取代void(0),也能得到相同的结果。

实际上undefined远比想象得要有用得多,我们在后续章节里还会多次接触到undefined这个特殊的值。

至此,我们对例子代码的分析就告一段落。这段代码的经典之处不但在于它实现的效果令人惊叹,还在于它在短短的几行指令中体现了客户端JavaScript中大多数重要的特性,这些特性包括我们前面提到的伪协议、全局变量、文档接口、集合对象、函数、内置对象、元素样式属性、定时器以及void()和undefined,除此以外还提到了代码中没有出现的闭包、函数实例化以及typeof操作符,这些特性几乎构成了客户端JavaScript的全部,在后面的章节中我们也将重点围绕着这些特性展开讨论,相信一段时间之后你再回头看这段代码,会有更加深刻的理解和新的收获。

JavaScript经典魔力代码的更多相关文章

  1. 《javascript经典入门》-day02

    <javascript经典入门>-day02 1.使用函数 1.1基本语法 function sayHello() { aler('Hello'); //...其他语句... } #关于函 ...

  2. 《javascript经典入门》-day01

    <javascript经典入门>-day01 1.了解JavaScript 01.浏览器每次加载和显示页面时,都在内存里创建页面及其全部元素的一个内部表示体系,,也就是DOM.在DOM里, ...

  3. 20道JavaScript经典面试题

    该篇文章整理了一些前端经典面试题,附带详解,涉及到JavaScript多方面知识点,满满都是干货-建议收藏阅读 前言 如果这篇文章有帮助到你,️关注+点赞️鼓励一下作者,文章公众号首发,关注 前端南玖 ...

  4. Javascript 语言精粹 代码片段合集

    Javascript 语言精粹 代码片段合集 标签:Douglas-Crockford Javascript 最佳实践 原文链接 更好的阅读体验 使用一个method 方法定义新方法 Function ...

  5. WebBrowser一点心得,如果在Javascript和Winform代码之间实现双向通信

    原文:WebBrowser一点心得,如果在Javascript和Winform代码之间实现双向通信 最近工作需要,学习了一下winform内嵌webbrowser控件,然后与htm页面中的javasc ...

  6. Notepad++ 配置 支持jquery、html、css、javascript、php代码提示

    原文:Notepad++ 配置 支持jquery.html.css.javascript.php代码提示 官网下载:http://notepad-plus-plus.org/ 获取插件的方法:打开软件 ...

  7. JavaScript经典作用域问题(转载)

    题目 var a = 10; function test(){ a = 100; console.log(a); console.log(this.a); var a; console.log(a); ...

  8. JavaScript 经典笔记

    JavaScript 是弱类型的语言,所以编译器不能检测出类型错误. JavaScript 依赖于全局变量来进行链接.所有编译单元的所有顶级变量被撮合到一个被称为全局对象(the global obj ...

  9. ASP.NET 前台Javascript调用后台代码 / 后台调用前台Javascript

    1:ASP.NET 前台Javascript调用后台代码 1.1:前台Javascript <script> function CallCs() { var str = "< ...

随机推荐

  1. css空格和去浮动的应用

    今天做了项目用到css,请教前端解决,第一个是记得css空格之间的关系是隶属关系,但是在元素中却是并列关系,如<div class="right_side_item_moban gra ...

  2. GIt/Github常用命令

    1)git init:初始化本地仓库 2)创建文件:touch read.txt 3)当操作本地的文件时,使用常用的命令,如(mv,ls..)就可以操作,当操作暂存区的文件时需要在命令前家git,并且 ...

  3. nexus 的使用及maven的配置

    一.nexus的安装 1.下载nexus(点解这里) 2.下载后解压文件,将解压后的nexus文件放在你自己想要的地方 3.配置环境变量(和配置java的环境变量一样) 4.安装和启动nexus 由于 ...

  4. WPF自定义Main函数

    第一步:在app.xaml.cs里加入以下代码: [STAThread] public static void Main(string[] args) { App app = new App(); a ...

  5. 解决使用angularjs时页面因为{{ }}闪烁的两种方式ng-bind,ng-cloak

    1.HTML加载含有{{ }}语法的元素后并不会立刻渲染它们,导致未渲染内容闪烁(Flash of Unrendered Content,FOUC).我可以用ng-bind将内容同元素绑定在一起避免F ...

  6. oracle中char,vchar,vchar2的区别与联系

    1.char是固定长度的,例如你定义某一列类型为char(20).那么即便你插入"abcde"5个字节,数据库也会在后面自动加上15个字节(可能为空格),以补足二十个字节. 2.v ...

  7. XMLHttpRequest state以及readystate的对应值

    status状态值长整形标准http状态码,定义如下: Number  Description  100 Continue101 Switching PRotocols200 OK201 Create ...

  8. 监听<input/>标签行为的方法总结

    一.内容改变 1.<input onchange="javascript:function()"/>方法 onchange可以替换为下面几种:oninput,onpro ...

  9. php stripslashes() addslashes() 解析

    stripslashes() 函数删除由 addslashes() 函数添加的反斜杠. 实例: <?php $str = "Is your name O\'reilly?"; ...

  10. php中magic_quotes_gpc函数详解

    magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post.get.cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊 ...