第15章 JavaScript基础
【学习重点】
- 了解JavaScript基础知识
- 熟悉常量和变量
- 能够使用表达式和运算符
- 正确使用语句
- 能够掌握数据类型和转换的基本方法
- 正确使用函数、对象、数组等核心知识和技法
- 能够编写简单的脚本,解决网页中常见特效和互动效果
15.1 JavaScript入门
JavaScript是一种轻量级、解释型的Web开发语言。现代浏览器都已嵌入了JavaScript引擎。/sc
15.1.1 在网页中插入JavaScript代码
使用<script>标签,可以把JavaScript源代码直接放到网页文档中。
<script>和</script>标签配合使用,作为脚本语言的标识符来分隔其它源代码,避免混淆。
一般来说,JavaScript代码可以放在网页中的任意位置。但是,根据W3C标准,<script>和<link>标签作为HTML文档的一个节点,也应该包含在<html>和</html>根节点内。
每个网页可以包含多个<script>标签,每个标签包含的代码被称为JavaScript脚本块。建议把功能相同或相近的代码放在一个脚本块中。适当时可以把通用脚本模块放在单独的JavaScript文件中,或者把它们封在一个独立的对象以方便调用。
15.1.2 使用JavaScript文件
JavaScript文件是一个文本类型的文件,在任何文本编辑器中都可以打开、编辑,JavaScript文件的扩展名是js。
引入JavaScript文件时,可以使用<script>标签实现,通过该标签的src属性指定JavaScript文件的URL即可。
15.1.3 JavaScript语法基础
1、语言编码
JavaScript语言建立在Unicode字符集基础上,在脚本中,用户可以使用双字节的字符命名常量、变量或函数等。
建议用户不要使用中文命名,但在注释中可以考虑中文字符。
2、大小写敏感
与HTML标签和CSS样式码不同,JavaScript对于大小写敏感。为了避免出错,建议使用小写字符命名变量;对于保留字可以根据系统的默认大小来输入;对于特定变量,可以使用大写字符,或者以大写字符开头。
对于复合型变量名称,可以遵循一般编程的驼峰式命名法——名称的第一个单词全部小写,后面的单词首字母大写。
3、代码格式化
JavaScript一般忽略分隔符,如空格符、制表符合换行符。在保证不引起歧义的情况下,用户可以利用分隔符对脚本进行排版。但不能在连在一起的变量名、关键字中间插入分隔符。
4、代码注释
JavaScript支持两种注释形式:
- 单行注释,以双斜杠表示
//这是单行注释
- 多行注释,以“/*”和“*/”分隔符进行标识
/* 多行注释 多行注释 */go
5、标签
在JavaScript脚本中可以加上标签,方便JavaScript程序进行快速定位。标签一般由一个合法的字符名称加上一个冒号组成。标签可以为该行设置一个标记,在结构体中使用break、continue等跳转语句跳出循环。
6、关键字和保留字
关键字是指JavaScript默认定义具有特殊含义的词汇,如指令名、语句名、函数名、方法名、对象名、属性名。
保留字就是现在还没使用,但预留以后作为关键字使用。
15.1.4 认识JavaScript语法特性
构成JavaScript语言的基本语素包括3种,与汉语语法类似,说明如下:
- 词
词是JavaScript语言的最小语义单元,包括常量、变量、运算符、表达式、指令、修饰符等。词之间以空格进行分隔。
- 句子
句子是由一个或多个词构成的完整逻辑部分,句子以分号作为结束标志,也可以只以换行符作为结束标志。
- 段落
段落是由一对大括号包含的一段代码,段落内容可以是一句或多句完整的句子,也可以在段落内嵌套另一个段落,形成结构嵌套。
段落前面可以添加修饰词——限制对象的谓词。谓词有域谓词(指明对象的作用域或作用范围)、逻辑谓词(逻辑关系)、函数谓词(函数名、函数参数等)。
JavaScript语言还大量使用标点符号作为命令或语法符号,如大括号{}、中括号和小括号等。
- 对象({})
对象都以左大括号({)开始,以右大括号(})结束,里面一个或多个“名/值”对,“名/值”对之间没有先后顺序关系。
每个“名/值”对内的“名称”和“值”之间使用冒号(:)进行分隔,而“名/值”对与“名/值”对之间使用逗号分隔。
使用点号可以引用对象的属性和方法,在调用对象方法时应在函数名称后面补加小括号。
- 数组([])
数组以左中括号([)开始,以右中括号(])结束,中间可以包含多值,值之间使用逗号分隔。数组(array)是值(value)的有序集合。
- 调用和逻辑分隔(())
在JavaScript中,小括号表示一个运算符,用于调用函数。小括号也可以作为逻辑分隔符,在定义函数时,放在函数名称的后面,用来分隔函数和参数。
15.2 常量和变量
JavaScript暂不支持constant关键字,不允许用户自定义常量,但是提供了几个默认常量供开发使用。
- Math.E:常量e,自然对数的底数;
- Math.LN10:10的自然对数;
- Math.LN2:2的自然对数;
- Math.LOG10E:以10为底的e的对数;
- Math.LOG2E:以2为底的e的对数;
- Math.PI:常量PI;
- Math.SQRT1_2:1/2的平方根;
- Math.SQRT2:2的平方根;
- Number.MAX_VALUE:可表示的最大的数;
- Number.MIN_VALUE:可表示的最小的数;
- Number.NaN:非数字值;
- Number.NEGATIVE_INFINITY:负无穷大,溢出时返回该值;
- Number.POSITIVE_INFINITY:正无穷大,溢出时返回该值。
JavaScript使用var关键字声明变量。
JavaScript也支持不使用var命令,直接使用未声明的变量,但建议先声明后使用。
声明变量之后,在没有初始化之前,则它的初始值为undefined(未定义的值)。
变量命名规则如下:
- 首字符必须是大写或小写的字母、下划线或美元符,后续的字母可以是字母、数字、下划线或美元符;
- 变量名称不能是JavaScript关键字或保留字;
- 变量名称长度任意,区分大小写。
还有一些软约束:
- 变量声明集中、置顶,如文档的前面、代码段的前面,或者函数内的上面;
- 使用局部变量,不要把所有的变量放在段首,如果仅在函数内使用,建议在函数内声明;
- 变量名应该易于理解;
- 声明变量之前,应该规划好,避免类似usrname与usrName混用现象。
在函数内部使用var关键字声明的变量就是私有变量,该变量的作用域仅限于当前函数体内,但是如果不使用var关键字定义的变量都是全局变量,不管是在函数内或者函数外,在整个页面脚本中都是可见的。
15.3 表达式和运算符
表达式是指可以运算,且必须返回一个确定的值的式子。表达式一般有常量、变量、运算符、字表达式构成。
值表达式的返回值为它本身,而变量表达式的返回值为变量存储或引用的值。
把简单的表达式合并为一个复杂的表达式,连接表达式的符号就是运算符。
运算符一般使用符号来表示,如“+”、“-”;也有些运算符使用关键字来表示,如deleter、void。
作用于运算符的子表达式被称为操作数。根据结合操作数的个数,JavaScript运算符可以分为:
- 一元运算符,把一个操作数运算后转换为另一个操作数;
- 二元运算符,结合两个操作数;
- 三元运算符,能够结合三格操作数,JavaScript仅定义了一个三元运算符(?:),相当于条件语句。
15.4 语句
语句就是JavaScript指令,可以设计程序的逻辑执行顺序。
15.4.1 表达式语句和语句块
如果在表达式的尾部附加一个分号就会形成一个表达式语句。JavaScript默认独立一行的表达式也是一个表达式语句。
语句块就是由大括号包含的一个或多个语句。
15.4.2 条件语句
程序的基本逻辑结构包括3种:顺序、选择和循环。大部分控制语句属于顺序结构,条件语句属于选择结构,包括if语句和switch语句两种。
1、if语句
if语句的基本语法如下:
if(condition) statements
其中condition是一个表达式,statement是一个句子或段落。当condition表达式的结果不是false,那么就执行statements从句的内容。
在if语句的基本形式上还可以扩展如下语法,表示condition表达式条件为true,则执行statements1从句,否则执行statements从句。
if (condition) statements1 else statements2
2、switch语句
对于多条件的嵌套结构,更简洁的方法是使用switch语句。语法如下:
switch (expression){ case label1: statement1; break; case label2: statement2; break; ... default : statementn; }
switch语句首先计算switch关键字后面的表达式,然后按出现的先后顺序计算case后面的表达式,直到找到与switch表达式的值等同(===)的值为止。case表达式通过等同运算来进行判断,因此表达式匹配的时候不进行类型转换。
15.4.3 循环语句
循环语句——能够重复执行相同操作的语句。两种基本语法形式:while语句和for语句。
1、while语句
while(condition){ statements }
每次循环前计算condition表达式。如果为true,执行循环体内的语句;如果为false,跳出循环,执行while语句后面的语句。
while语句有一种变体:
do statements while(condition);
首先执行statement一次,在每次循环结束之后计算condition条件。
2、for语句
比while语句简洁
for([initial-expression;][condition;][increment-expression]){ statements }
先计算初始化表达式(initial-expression),典型情况下用于初始化计数器变量,可选用var声明新变量;
条件测试是可选的,如果缺省则条件始终为true,除非循环体内使用break语句,否则不能终止循环;
increment-expression表达式用于更新或自增计数器变量。
15.4.4 跳转语句
跳转语句能够从所在的分支、循环或从函数调用返回的语句跳出。JavaScript的跳出语句包括3种:break、continue、return。
break用来跳出循环或者switch语句。语法为:
break;
跳转语句可以与标记结合使用,以实现跳转到指定的行,而不是仅仅跳出循环体。
x: for(a=1; a<10; a++){ document.write("<br />"+a+"<br />"); for(var b=1;b<10;b++){ if (a>5) break x; } }
continue语句的用法与break类似,但是continue不会退出循环,而是重新执行循环语句。continue只能用在循环体中。
return用来指定函数的返回值,只能够用在函数或者闭包中。语法如下:
return [expression]
先计算expression表达式,然后返回表达式的值,并将控制逻辑从函数体内返回。
15.4.5 异常处理语句
异常表示一种非正常的信息,提示程序出现了错误。JavaScript通过一定的机制使异常信号暴露出来,这个操作被称为抛出(throw);使用异常处理语句捕获(catch)这个异常,进行处理。
JavaScript中使用try、catch、finally来作异常处理的语句。语法如下:
try { //执行语句 CreateException(); } catch(ex) //捕获异常 { alert(ex.number+"\n"+ex.description); } finally //最后必须执行的语句 { alert("end"); }
15.4.6 var语句和function语句变量
var语句声明一个或多个变量,可以在声明变量时进行初始化。默认变量初始值为undefined。
function用来定义函数,基本形式如下:
function [name][param],[param],...[param]){ statements }
name表示函数的名称,param表示要传递给函数的参数名称,一个函数最多可以有255个参数。
15.4.7 with语句和空语句
with语句能够为一组语句创建缺省的对象,用法如下:
with(object){ statements }
with语句能够破变量的作用域链,不建议使用。
空语句只有一个独立的分号,作用是创建一个主体为空的条件或者循环。如:
while(true){ ; }
上面代码创建了一个主体为空的循环。
15.5 数据类型
JavaScript中,数据存在两种截然不同的存储方式。一种是直接存储数据,称为值类型数据;一种是存储数据的空间地址来间接保存数据,称为引用型数据。
15.5.1 数值
JavaScript包含3种基本数据类型:数值、字符串和布尔值。
JavaScript数值不区分整型和浮点数,所有数值都为浮点型数值。
使用toString()方法可以把数值转换为字符串。
使用数值与空字符串相加,即可把数值转换为字符串。
var a=100; var c=a+""; alert(typeof(c));
15.5.2 字符串
字符串由Unicode字符、数字、标点符号等组成的字符序列,必须用单引号或双引号包括起来。所有字符应该在同一行内书写。
var str1="字符串序列"; var str2="‘JavaScript‘不是‘Java‘"; var str3=‘<meta charset="utf-8">‘;
使用parseInt()和parseFloat()方法可以把字符串转换为数值。
便捷方法:让字符串与1相乘,即可把字符串快速转换为数值。
15.5.3 布尔值
布尔型数据仅两个值:true和false,分别表示逻辑的真和假。布尔值多用在逻辑运算、比较运算中,或者作为条件语句或运算符的条件而使用。
要把任何值转换为布尔值数据,在值的前面增加两个叹号即可。
任何非0数字转换为布尔值为true,而0转换为布尔值为false。
任何非空字符串转换为布尔值为true,而空格转换为布尔值为false。
如果把布尔值转换为字符串,则true为“true”,false为“false”。
如果把布尔值转换为数字,则true为1,false为0。
JavaScript语法系统有一组假值,布尔值都是false,具体如下:
0 //Number NaN //Number ‘‘ //String false //Boolean null //Object undefined //Undefined
15.5.4 null和undefined
null是Null类型的值,表示空值。当对象为空,或者变量没有引用任何对象,返回值为null。
undefined表示未定义的值,当变量未初始化时,会默认其值为undefined。
15.5.5 引用型数据
引用型数据包括:数组、对象和函数等。将在下面各节详解。
15.6 函数
15.6.1 定义函数
定义函数的方法有两种:
- 使用function语句声明函数;
- 通过function对象来构造函数。
使用function来定义函数有两种方式:
//方式1:命名函数 function f() { //函数体 } //方式2:匿名函数 var f=function(){ //函数体 }
匿名函数的方法也被称为引用式函数或函数表达式,即把函数看做一个复杂的表达式,并把表达式赋予给变量。
使用Function对象构造函数的语法如下:
var function_name=new Function(arg1, arg2, ..., argN, function_body)
每个arg都是一个函数参数,最后一个参数是函数主体(要执行的代码)。Function()的所有参数必须是字符串。
15.6.2 调用函数
调用函数使用小括号运算符来实现。在括号运算符内部可以包含多个参数列表,参数之间通过逗号分隔。例如:
function f(){ return "Hello, World!"; //设置函数返回值 } document.write(f()); //调用函数,并输出返回值
一个函数可以包含多个return语句,但是在调用函数时只有第一个return语句被执行,且该return后面的表达式的值作为函数的返回值被返回,return语句后面的代码将被忽略掉。
函数的返回值没有类型限制,它可以返回任意类型的值。
15.6.3 函数参数
参数可以分为两种:形参和实参。
- 形参是定义函数时,传递给函数的参数,形式上参数;
- 实参是当函数被调用时,传给函数的参数。
如果形参多于实参,多出的形参值为undefined;如果形参少于实参,多出的实参被忽略掉。
JavaScript定义了Arguments对象,利用该对象可以快速操纵函数的实参。使用arguments.length可以获取函数实参的个数,使用数组下标(arguments[n])可以获取实际传递给函数的每个参数值。
15.6.4 函数应用
1、匿名函数
当只需要一次性使用函数时,使用匿名函数会更加有效率。
var z=function(x,y){ return (x+y)/2; } (23,35); //返回29
2、函数作为值
函数实际上是一种结构复杂的数据,因此可以把它作为值赋予给其它变量。
var a=function(x, y) { return (x+y)/2; } alert ( a(12,33) ); //返回22.5
3、函数作为参数
函数作为值可以传递,因此可以把函数作为参数传递给另一个函数,也可以作为返回值。
4、函数作为表达式
函数可以参与到表达式运算中。
15.6.5 闭包函数
闭包是一个拥有许多变量和绑定了这些变量的环境的表达式。闭包函数(外部函数)被调用后,它的变量不会消失,仍然被内部函数所使用,而且所有的内部函数拥有对外部函数的访问权限。
15.7 对象
对象时面对对象编程的核心概念,它是已经命名的数据集合,也是一种更复杂的数据结构。
15.7.1 创建对象
对象是由new运算符生成,生成对象的函数被称为类(或构造函数、对象类型)。生成的对象被称为类的实例,简称对象。
var o=new Object(); //构造原型对象 var date=new Date(); //构造日期对象 var ptn=new RegExp("ab+c","i"); //构造正则表达式对象
也可以通过大括号定义对象直接量,用法如下:
{
name: value,
name1:value1,
......
}
对象直接量由一个列表构成,元素是用冒号分隔的属性/值对,元素之间用逗号分开。
15.7.2 访问对象
可以通过点号运算符(.)来访问对象的属性,如
var point={ x:2.3, y:-1.2 }; var x=point.x; //访问对象的属性值
当属性值为函数时,该属性就被称为对象的方法,使用小括号可以访问该方法。
var point={ f: function(){ //对象方法 return this.y; //返回当前对象属性y的值 }, y:1.2 //对象属性 }; var y=point.f(); //调用对象的方法
上面代码中,关键字this代表当前对象,这里的this总是指向调用当前方法的对象point。
当属性为对象时,就可以设计嵌套对象,可以连续使用点号运算符访问内部对象。
var point= { //外部对象 x : { //嵌套对象 a : 1, //内部对象的属性 b : 2 }, y : 1.2 //外部对象的属性 }; var a= point.x.a; //访问嵌套对象的属性值
也可以通过集合运算符([])来访问对象的属性,此时可以使用字符串下标来表示属性。
var point= { //外部对象 x : { //嵌套对象 a : 1, //内部对象的属性 b : 2 }, y : 1.2 //外部对象的属性 }; var a= point["x"]["a"]; //访问嵌套对象的属性值
15.8 数组
对象是无序的数据集合,而数组(Array)是一组有序数据集合。它们之间可以相互转换。
15.8.1 定义数组
通过构造函数Array()和运算符new来实现。
(1)定义空数组
var a=new Array();
(2)定义带有参数的数组
var a=new Array(1,2,3,"4","5");
数组中每个参数都表示数组的一个元素值,数组的元素没有类型限制。可以通过数组下标定位元素,通过数组的length属性确定数组的长度。
(3)定义指定长度的数组
var a=new Array(6);
没有为元素初始化赋值,它们的初始值都是undefined。
定义数组时,可以省略new运算符,直接使用Array()函数来实现。
(4)定义数组直接量
var a=[1,2,3,"4","5"];
15.8.2 存取元素
使用[]运算符可以存取数组元素的值。方括号左边是数组的应用,方括号内是非负整数值的表达式。如:
var a=[1,2,3,"4","5"]; a[2]=2; //修改第二个元素的值 alert(a[2]); //提示为2
数组的大小不固定,可以动态增加或删除数组元素。
1、通过改变数组的length属性来实现
var a=[1,2,3,4,5]; a.length=4; document.write(a);
当改变数组的长度时,会自动在数组的末尾增加或删除元素,以实现改变数组的大小。
使用delete运算符可以删除数组元素的值,但是不会改变length属性的值。
2、使用push()和pop()方法来操作数组
push()可以在数组的末尾插入一个或多个元素,pop()可以依次把它们从数组中删除。
var a=[]; //定义一个空数组 a.push(1,2,3); //得到数组[1,2,3] a.push(4,5); //得到数组[1,2,3,4,5] a.pop(); //得到数组[1,2,3,4]
push()可以带多个任意类型的参数,按顺序插入到数组末尾,并返回操作后数组的长度。
pop()方法不带参数,返回数组中最后一个元素的值。
3、使用unshift()和shift()方法
和push()/pop()方法操作类似,但是作用于数组的头部。
4、使用splice()方法
通用删除和插入元素的方法,可以在数组指定的位置开始删除或插入元素。
3个参数:指定插入的起始位置,指定要删除元素的个数,表示插入的具体元素。
var a=[1,2,3,4,5,6]; var b=a.splice(2,2); document.write(a+"<br />"); //输出[1,2,5,6] document.write(b); //输出[3,4]
var a=[1,2,3,4,5,6]; var b=a.splice(2,2,7,8,9); document.write(a+"<br />"); //输出[1,2,7,8,9,5,6] document.write(b); //输出[3,4]
15.8.3 数组应用
1、数组与字符串互转
join()可以把数组转换为多种形式的字符串,join()包含一个参数——用来定义合并元素的连字符。如果不提供参数,默认以逗号连接。
var a=[1,2,3,4,5]; a=a.join("-"); document.write("a类型="+typeof(a)+"<br />"); document.write("a的值="+a);
split()可以把字符串劈开为一个数组,包含两个参数——指定劈开的分隔符,指定返回数组的长度。
var a=[1,2,3,4,5]; a=a.join("-"); var s=a.split("-"); document.write("s类型="+typeof(s)+"<br />"); document.write("s的值="+s);
2、数组排顺
使用reverse()方法可以颠倒数组元素的顺序,该方法是在原数组基础上进行操作,不会新建数组。
sort()方法能够对于数组中的元素进行排序,排序的方法由其参数决定。这个参数是一个比较两个元素值的闭包。如果省略参数,则sort()方法按默认规则排序。
var a=[3,2,5,1,4]; var f=function(x,y){ return y-x; }; var b=a.sort(f); document.write(b); //输出[5,4,3,2,1]
3、连接数组
concat()方法能够把该方法中的参数追加到指定数组中,形成新的数组。如果concat()方法中的参数包含数组,则把数组元素展开添加到数组中。
var a=[1,2,3,4,5]; var b=a.concat([4,5],[1,[2,3]]); document.write(b); //输出[1,2,3,4,5,4,5,1,2,3]
4、截取子数组
slice()方法将返回数组中指定的片段,包含两个参数——要返回子数组在原数组中的起止点。第一个参数指定的元素被截取,第二个参数指定的元素不被截取。
var a=[1,2,3,4,5,6,7,8,9]; var b=a.slice(2,5); document.write(b); //输出[3,4,5]