学习内容
- JavaScript函数
- JavaScript类和对象
- 解析JSON数据
能力目标
- 深入了解JavaScript函数
- 熟悉JavaScript面向对象编程
- 熟练进行JSON数据解析
本章简介
自JavaScript诞生以来,其功能由最初简单地实现客户端有效性验证发展到构建丰富的用户界面效果,始终从用户角度提升体验效果。前面我们已经学习了JavaScript的基础理论知识,包括其语法、变量、函数、事件、数组及BOM / DOM对象,可以顺利地进行前端开发。但是,JavaScript还有一些高级技术需要我们了解和掌握,像类、对象、匿名函数、JSON等,本章将学习这些知识。
核心技能部分
1.1 JavaScript回顾
JavaScript是一种基于对象和事件驱动的脚本语言,由浏览器负责解释、执行。JavaScript分为三大部分:ECMAScript、BOM和DOM。
ECMAScript是核心,包括语法、变量和数据类型、运算符、逻辑控制语句、关键字和保留字等。BOM即浏览器对象模型,DOM即文档对象模型。
1.2 函数
JavaScript的核心是函数,大部分的业务逻辑和数据处理都需要交给函数来实现。JavaScript函数分为命名函数、匿名函数、内部函数和回调函数等。
1.2.1 命名函数
命名函数,顾名思义就是该函数有名字,我们需要通过函数名来调用这个函数。创建命名函数的语法如下所示:
语法
function函数名(参数列表){ 执行语句 return返回值; } |
下面使用命名函数实现一个打招呼的简单例子,参考代码如下所示。
示例1.1
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.1</title>
</head>
<script>
function sayHello(name)
{
alert("hello," + name);
}
</script>
<body οnlοad="sayHello('Jack')">
</body>
</html>
上述代码定义了一个名字叫sayHello的函数,并在页面的加载事件中调用了该函数。在前面学习JavaScript时,我们写的其实都是命名函数。
与C#、Java等语言相比,JavaScript函数的参数更具有灵活性,具体表现在以下几个方面:
函数即使声明了参数,调用时也可以不给参数传值。
函数被调用时将自动创建一个arguments隐含对象,负责管理参数。
参数和返回值可以是任何类型。
函数可以不需要return语句返回值,没有return语句时函数的返回值是undefined。
arguments是函数的隐含对象,调用函数时传递的参数值都默认封装到了该对象(数组)中。下面通过一个示例演示arguments隐含对象的用法,参考代码如示例1.2所示。
示例1.2
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.2</title>
</head>
<body>
<script type="text/javascript">
function fnArgs(){
var result = '';
for (var i = 0; i < arguments.length; i++){
result += arguments[i] + ',';
}
result = result.substring(0, result.length - 1);
return result;
}
alert('为fnArgs()函数传递的参数的值是:' + fnArgs(3, '郑州', 3.14));
</script>
</body>
</html>
上述代码定义了一个名字是fnArgs的无参函数,在调用该函数时传递了3个值示。
1.2.2 匿名函数
在JavaScript中,函数可以没有名字,称之为匿名函数。下面通过一个示例来演示匿名函数的用法,参考代码如下所示。
示例1.3
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.3</title>
</head>
<body>
</body>
</html>
<script>
//创建匿名函数
var fn=function(){
return a+b;
};
//通过变量名调用匿名函数
var a=10,b=20;
alert(fn(a,b));
</script>
上述代码在使用function关键字创建函数时并没有给函数命名,而是把函数赋值给一个变量,通过该变量来调用函数。
在JavaScript中,可以把某个函数定义在另一个函数内,称之为内部函数。内部函数可以出现在命名函数里,也可以出现在匿名函数中。
下面通过一个示例来演示内部函数的用法,参考代码如下所示。
示例1.4
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.4</title>
</head>
<body>
</body>
</html>
<script>
//在命名函数中创建内部函数
function sayHello(name)
{
function temp(){
alert("hello,"+name);
}
temp();
}
//调用
sayHello("Jack");
//在匿名函数中创建内部函数
var func=function(){
return function(){
alert("函数返回值是一个内部函数");
}
};
//调用
func()();
</script>
上述代码分别在命名函数和匿名函数中创建了内部函数。对于命名函数中的内部函数来说,定义和调用都需要放在命名函数内。对于匿名函数中的内部函数来说,由于函数没名字,所以在定义内部函数的同时就需要使用return关键字把这个函数返回。另外,在调用匿名内部函数时,需要两个()。
1.2.4 回调函数
回调即CallBack,它不是JavaScript语言特有的,属于一种编程设计,早在C语言中就已经出现了。通常情况下,当我们需要调用某个类或类的方法时会这样编写代码:
Obj o=new Obj(); //创建Obj类的对象
o.m1(); //调用m1方法
m1方法在编译期已经确定,开发人员知道运行时会执行什么代码,这就是我们经常说的“调用”,即Call。但有的时候Call并不能满足业务需求,我们需要“回调”,即CallBack,下面是一个回调的例子。
示例1.5
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.5</title>
</head>
<body>
<script>
function test(name,cb){
document.write(name+"在"+cb());
}
function cb1(){
return "吃饭";
}
function cb2(){
return "学习";
}
test("张三丰",cb1);
</script>
</body>
</html>
上述代码定义了三个函数,在调用test函数时,把cb1或cb2函数作为参数进行传递
test函数在编译期无法确定接下来执行什么代码,它将变得非常灵活,传过来什么函数就执行什么代码。BOM中的定时器setTimeOut和setInterval函数采用的就是回调函数的设计,因为定时器在编译期无法确定将来会调用什么函数、执行什么代码。
1.3 JavaScript面向对象编程基础
JavaScript是基于对象的解释性语言,所有数据都是对象。在JavaScript中并没有class的概念,但是可以通过对象和类的模拟来实现面向对象编程。
1.3.1 类的模拟
ECMAScript内置了几种引用类型:Object、Boolean、Number、String。其实JavaScript也支持自定义类型。ECMAScript最令人感兴趣的可能莫过于函数实际上就是功能完整的类,所以我们可以使用函数来实现类的模拟。
类是自定义类型,只有定义后才能用于创建对象。在JavaScript中没有class,但可以通过使用关键字function和this定义类模板。具体语法如下所示:
语法
function 类名 (参数1, 参数2, … 参数n) { this.属性名=参数1; this.属性名=参数n; this.方法名=function(){ }; ... ... } |
下面是通过function自定义一个类的例子,参考代码如下所示。
示例1.6
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.6</title>
</head>
<body>
<script>
function Teacher(n,s,a){
this.name=n;
this.sex=s;
this.age=a;
this.getDetails=function(){
document.write('教员的姓名:'+this.name+'<br>教员的性别:'+this.sex+'<br>
教员的年龄:'+this.age);
}
}
//创建对象
var tea=new Teacher('Mary','女',25);
//调用方法
tea.getDetails();
</script>
</body>
</html>
上述代码首先使用function模拟定义了一个教员类,并通过this关键字定义了该类的一些属性和方法,然后通过new关键字创建了教员类的一个对象,并调用了该对象的getDetails方法。
1.3.2 对象
在JavaScript中,对象被定义为无序属性的集合,属性可以是任何类型的值,包括其他对象或函数。函数作为属性值时称为“方法”,即对象的行为。
在JavaScript中,使用new关键字调用构造函数创建对象。
语法
var 对象名 = new 构造函数(); |
对象的属性都通过“.”运算符访问。如果访问值是null对象的属性,将出现空引用错误。与普通变量函数相同,对象的属性可以动态生成。将某个属性值设置为null表示删除该属性;在函数内部的对象,函数执行完毕后将自动释放所占用的资源;在函数外部定义的对象,将其设置为null后、垃圾收集器将释放其占用的资源。
JavaScript还提供了一些内置对象,我们需要了解一下,主要有 Object、Function、Array、String、Date、RegExp、Math、Error等。
Ø Object 对象:它是所有对象的基础,其他所有对象都从Object对象扩展而来,这一切都通过原型实现。原型是对象的一个属性,即prototype。Prototype本身是一个对象,每个对象都具有此属性。JavaScript 中每个对象本身都不包含具体的属性(但可以动态添加),而是通过原型进行属性的共享。当获取一个对象的属性时,系统首先检测对象是否直接包含该属性,如果不包含则从原型属性中查找;如果仍未找到,则返回 undefined。
关于原型的内容会在后面做详细介绍。
Ø Function对象:我们经常编写的函数也是对象(JavaScript 中一切皆对象),所以当使用 function 关键字定义函数时,实际上是在系统内部创建了一个 Function 对象。以下语法是等价的:
var 函数名 =new Function(形参1,形参2,…,形参n,函数体);
function 函数名(形参1,形参2,…,形参n)(函数体;}
上述语法中,前一种方式直接调用构造函数创建 Function 对象,后一种方式使用 function 关键字定义函数对象。
Ø Error对象:在JavaScript中,代码在运行时会产生异常对象Error对象,并且可以作为参数传递给catch子句进行处理,也可以使用new关键字创建自定义的Error对象。该对象有一个message属性用来获得系统异常提示信息。JavaScript中的异常处理跟Java类似,语法如下所示:
语法
<script>
try{
//代码
}
catch(e) { //e就是产生的异常对象Error
//处理
}
finally{
//代码
}
</script>
下面我们通过一个例子来演示JavaScript异常处理和Error对象的使用。
示例1.7
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.7</title>
</head>
<body>
<script>
try
{
document.getElementById("vtn").value="test";
}
catch(e)
{
alert(e.message+"\n对象不存在");
}
</script>
</body>
</html>
由于页面上没有id是vtn的元素,所以上述代码在运行时会发生异常,运行效果如图1.1.9所示。
图1.1.9 异常处理
除了系统抛出异常外,开发人员也可以根据业务需求人工抛出异常,例如下面的代码。
示例1.8
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.8</title>
</head>
<body>
请输入分数(百分制):<input type="text" id="vtn" οnblur="check()"/>
<script>
function check()
{
try
{
var score=parseFloat(document.getElementById("vtn").value);
if(score<0||score>100)
throw new Error("成绩输入错误");
}
catch(e)
{
alert(e.message);
}
}
</script>
</body>
</html>
当用户输入的成绩不在0~100之间时,上述代码生成了一个Error对象并使用throw关键字进行了抛出,运行效果如图1.1.10所示。
图1.1.10 抛出异常
1.4 JavaScript处理JSON格式数据
1.4.1 JSON
JSON即JavaScript Object Notation,是JavaScript对象原生的一种表示形式。它是一种轻量级的、纯文本的,用来存储、传递和交换文本信息,类似于XML,但是比XML更小、更快、更容易解析。
JSON的语法规则如下所示:
var 对象名 = {
属性1 : 属性值,
属性2 : 属性值,
函数 : function(){
//代码
}
... ...
};
属性的值可以是:
数字(整数或浮点数)
字符串(必须放在双引号中)
布尔值
null
下面我们通过一个例子来演示JSON的用法,参考代码如下所示。
示例1.9
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.9</title>
</head>
<body>
<script>
var student= {
name:"",
age:56,
address:"河南省郑州市",
sayHello:function()
{
alert("大家好,我是"+this.name);
}
};
student.name="张无忌";
student.sayHello();
</script></body>
</html>
上述代码使用JSON创建了一个名字是student的对象,包括3个属性和一个函数。
JSON也可以以数组的形式一次存储多个对象,语法如下所示:
var 对象数组名 = [
{ 属性1 : 属性值 , 属性2 : 属性值 },
{ 属性1 : 属性值 , 属性2 : 属性值 },
{ 属性1 : 属性值 , 属性2 : 属性值 }... ...
];
下面通过一个例子演示使用JSON存储多个员工的写法,参考代码如下所示。
示例1.10
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.10</title>
</head>
<body>
<script>
var employees = [
{ firstName:"Bill" , lastName:"Gates" },
{ firstName:"George" , lastName:"Bush" },
{ firstName:"Thomas" , lastName: "Carter" }
];
alert("一共有"+employees.length+"个员工:\n"+employees[0].firstName+"\n"+employees[1].firstName+
"\n"+employees[2].firstName);
</script>
</body>
</html>
上述代码通过JSON以数组的形式创建了3个员工对象,在获取这些对象的信息时需要通过下标。
1.4.2 解析JSON
JSON 最常见的用法是Web服务器把从数据库中读取出来的数据转换成JSON格式的字符串,然后输出到客户端,这时客户端就需要把JSON格式的字符串转换为JavaScript对象,然后在网页中才能使用这些数据。
在客户端解析JSON格式字符串的方式有两种:
eval函数
JSON解析器,即JSON . parse ( )
eval函数使用的是JavaScript编译器,所以能够执行任何JavaScript代码,包括解析JSON 字符串。在使用的时候必须把文本包围在一对小括号中,这样才能避免语法错误。
语法
eval( "(" + JSON字符串 + ")" );
下面通过一个例子来演示如何使用eval来解析JSON字符串,参考代码如下所示。
示例1.11
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.11</title>
</head>
<body>
<script>
//假设JsonText是从Web服务器端返回的JSON格式的字符串
var JsonText='{"persons":[{"name":"jordan","sex":"m","age":"40"},
{"name":"bryant","sex":"m","age":"28"}]}';
var myjson = eval("("+JsonText+")");
document.writeln('转换后的JSON对象:' + myjson);
document.writeln('<br>myjson[0].name=' + myjson.persons[0].name);
</script>
</body>
</html>
上述代码使用eval函数把一个JSON格式的字符串解析成了一个对象,并输出了相关信息。
虽然eval函数可以解析JSON格式的字符串,但是建议开发人员要慎用此函数,因为该函数可以编译和执行任何JavaScript代码,存在安全隐患。
使用JSON解析器(parse函数)将JSON字符串解析为JavaScript对象是更安全的做法。JSON解析器只能识别JSON 文本,而不会编译脚本。较新的浏览器和最新的ECMAScript标准中均包含了原生的对JSON的支持,见表
浏览器支持 |
JS库(框架)支持 |
Firefox (Mozilla) 3.5 |
jQuery |
Internet Explorer 8 |
Yahoo UI |
Chrome |
Prototype |
Opera 10 |
Dojo |
Safari 4 |
ECMAScript 1.5 |
下面通过一个示例来演示JSON解析器的用法,参考代码如下所示。
示例1.12
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>示例1.12</title>
</head>
<body>
<script>
//假设JsonText是从Web服务器端返回的JSON格式的字符串
var JsonText='{"persons":[{"name":"jordan","sex":"m","age":"40"},
{"name":"bryant","sex":"m","age":"28"}]}';
var myData = JSON.parse(JsonText);
document.writeln('<br>转换后的JSON对象:' + myData);
document.writeln('<br>myData[1].name=' + myData.persons[1].name);
</script>
</body>
</html>
上述代码使用JSON解析器的parse方法把一个JSON格式的字符串解析成了一个对象,并输出了相关信息。
经过测试,JSON解析器在Firefox 、Chrome等浏览器上均能正常使用。
本章总结
本章主要学习了三方面的内容:函数、面向对象编程基础和处理JSON格式数据。函数包括命名函数、匿名函数、内部函数和回调函数,其中命名函数和匿名函数使用较多。面向对象基础部分讲解了最简单的类的模拟和对象的创建,为后续课程的学习进行铺垫。JavaScript处理JSON数据要求大家必须熟练掌握,这在实际开发中应用频繁。
任务实训部分
1:实现简易计算器
训练技能点
面向对象编程
函数的定义和调用
需求说明
使用面向对象的编程思想实现简易计算器,首先自定义一个计算器类,包括两个属
性:需要进行运算的第一个数和第二个数;定义四个方法分别实现加、减、乘、除
运算。
实现步骤
(1)实现简易计算器界面
(2)自定义计算器类,参考代码如下所示。
function Cal()
{
this.num1=0;
this.num2=0;
this.jia=function(){
return this.num1+this.num2;
};
this.jian=function(){
return this.num1-this.num2;
};
this.cheng=function(){
return this.num1*this.num2;
};
this.chu=function(){
return this.num1/this.num2;
};
}
(3)在【计算】按钮的单击事件中创建一个计算器类的对象并调用相应的方法实现计
算功能
2:客户类
训练技能点
类的定义
对象的使用
需求说明
先定义一个Customer类,属性:姓名、性别、年龄和电话;方法:客户消费;然
后创建对象并调用方法进行测试。
3:解析JSON数据
训练技能点
JavaScript解析JSON
需求说明
定义一个JSON对象,存储3个学生信息(姓名、性别、成绩);并逐行输出该
3个学生的所有信息。
4:解析JSON数据
训练技能点
JavaScript解析JSON
需求说明
定义一个JSON对象,存储3个省份信息;再定义三个JSON对象,存储三个省份
对应的城市信息。把省份信息和城市信息分别填充到两个下拉列表框中,并实现
级联特效。
实现步骤
(1)实现省市级联界面
(2)定义一个JSON对象存储省份信息,参考代码如下所示。
var p= [
{ pname:"河南省" , pvalue:"hn" },
{ pname:"广东省" , pvalue:"gd" },
{ pname:"山东省" , pvalue: "sd" }
];
(3)定义三个JSON对象存储城市信息
(4)在页面加载时把JSON对象填充到两个下拉列表框中,部分参考代码如下所示。
for(var j=0;j<p.length;j++)
{
var op=new Option(p[j].pname,p[j].pvalue);
document.getElementById("province").options.add(op);
}
(5)省份下拉列表框发生改变时实现级联效果
巩固练习
一、选择题
1. 以下关于JavaScript的说法正确的是()。
A. JavaScript中的函数都是有名字的,否则无法调用
B. JavaScript和Java一样使用class关键字定义类
C. JavaScript中没有类的概念,但是可以通过函数进行模拟
D. BOM和DOM是一样的,叫法不同而已
2. 以下关于JavaScript函数的说法正确的是()。
A. 在调用函数时,必须匹配函数参数的个数、类型
B. 函数可以有返回值,也可以没有返回值
C. 内部函数必须定义在命名函数里,否则无法调用
D. 回调函数是JavaScript独有的一种设计
3. 以下关于JavaScript面向对象编程的说法错误的是()。
A. JavaScript不支持自定义数据类型
B. JavaScript使用new创建对象
C. JavaScript中的函数也是对象
D. JavaScript不支持异常处理
4. 下列关于JSON说法错误的是()。
A. JSON是一种数据存储格式
B. JSON是Java原生对象
C. JSON一次只能存储单个对象
二、上机练习
定义一个JSON数组存储3本图书信息,包括图书名、作者和价格,然后使用JavaScript进行解析并输出所有的图书信息。