本文系统性的介绍JavaScript编程的基础知识,并编写案例程序。
JavaScript
赋予了超能力,它是真正的web编程语言,它允许您在网页中添加行为。不再有枯燥无味的静态页面,它们用JavaScript能够接触用户,对有趣的事件做出反应。从Web后端获取数据用于网页显示,在网页中绘制图形等等。一旦掌握了JavaScript
,可以为用户创建全新的行为。
JavaScript
不仅是最流行的编程语言,所有的现代浏览器作为运行环境
都支持它;JavaScript
甚至扩展并嵌入了许多浏览器外部的环境
。
如果您习惯于在网页中创建结构、内容、布局和样式,是不是也该添加一些行为逻辑?现在,页面不需要只静
在那里。伟大的页面应该是动态的
、交互式的
,它们应该以新的方式与用户一起工作
。这就是JavaScript
的作用所在
。先来看看JavaScript
如何融入网页生态系统。
您已经知道我们使用HTML
或超文本标记语言
来指定页面的所有内容及其结构,如段落、标题和章节。而且您已经知道,我们使用CSS
或层叠样式表
来指定HTML
的呈现方式,如颜色、字体、边框、边距和页面布局。CSS
为您提供样式,并且它以与页面结构分离的方式实现样式。
因此,让我们将JavaScript
、HTML
和CSS
的结合起来。JavaScript
允许您在网页中创建行为逻辑
。当用户点击一个按钮
来提交表单输入,将请求
发送到Web服务器
,从其上得到响应
获取一些数据并显示它们。JavaScript
为您提供了一种将编程添加到页面的方法,以便您可以计算、反应、绘制、通信、警报、更改、更新、更改等等任何动态
的事情,这就是JavaScript
的作用。
JavaScript是脚本型
的编程语言,在编程界相当独特。若使用传统编译型
的编程语言,必须编写、编译、链接和部署
的流程才能执行它。而使用JavaScript,需要做的就是将JavaScript直接写入HTML页面,然后将其加载到浏览器中。从那里,浏览器作为运行环境将开始解释执行
这些脚本代码。让我们看看这是如何做到的:
① 编写程序
可以像往常一样使用HTML内容和CSS样式创建页面。还可以在页面中包含JavaScript。就像HTML和CSS一样,您可以将所有内容放在一个文件中,也可以将JavaScript放在自己的文件中,将其包含在页面中。
② 加载程序
像往常一样,将浏览器指向页面。当浏览器看到代码时,它立即开始解析代码,准备执行它。注意,像HTML和CSS一样,如果浏览器在代码中发现错误,它将尽最大努力继续移动并阅读更多的JavaScript、HTML和CSS。它最不想做的事情就是不能给用户一个页面来查看。为了将来的引用,浏览器还构建了JavaScript可以使用的HTML页面的“对象模型”。
③ 执行程序
浏览器在页面中遇到JavaScript代码时立即开始执行代码,并在页面的整个生命周期内继续执行代码。与早期版本的JavaScript不同,如今版本的JavaScript是一个强大的平台,它使用高级编译技术与许多本地的编程语言几乎相同的速度执行代码。
如果你不知道如何将JavaScript放到页面中,就无法使用JavaScript。那么,怎么做到的?当然,使用<script>
标记元素!让我们看一个案例网页,并使用<script>
标记元素添加一些动态行为。现在,不必关注在<script>
标记元素中添加的内容信息,其目标是让一些程序执行起来。
清单 1:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>一寸光阴一寸金</title>
<style>
.calendar {
width: 300px;
height: 360px;
margin: 100px auto;
background-color: #59ACFF;
text-align: center;
color: #C1DBF5;
}
.calendar p {
color: #ffffff;
font: 400 18px/80px "微软雅黑";
}
#nowdate {
display: block;
height: 100px;
width: 100px;
background-color: #FF9600;
text-align: center;
margin: 0 auto;
font: 700 60px/100px "微软雅黑";
color: #ffffff;
}
.calendar strong {
margin: 20px auto;
padding: 5px;
display: block;
width: 260px;
height: 40px;
color: #ffffff;
font: 500 20px/26px "微软雅黑";
border-top: dashed 1px #ffffff;
}
#time {
color: #ffffff;
font: 500 20px/40px "微软雅黑";
}
</style>
<script>
window.onload = function() {
//当前年月日ID
var fulldate = document.getElementById("fulldate");
//当前日 ID
var nowdate = document.getElementById("nowdate");
//计时ID
var time = document.getElementById("time");
//问候语ID
var saying = document.getElementById("saying");
//获取现在的年月日小时
var fullTime = new Date();
var year = fullTime.getFullYear(); // 年
var month = fullTime.getMonth(); // 月
var date = fullTime.getDate(); // 日
var hours = fullTime.getHours(); // 小时
var dayArr = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
//设置年月日
fulldate.innerHTML = year + " 年 " + (month + 1) + " 月 " + date + " 日 " + dayArr[fullTime.getDay()];
//设置当前日
nowdate.innerHTML = date;
//当前时间名言
saying.innerHTML = "时刻即光阴,一寸光阴一寸金";
setInterval(getTime, 1000); // 开启定时器
function getTime() {
var myDate = new Date(); // 得到最新的时间
var h = myDate.getHours(); // 获取小时
h = h > 9 ? h : "0" + h; // 如果小时数字小于10,则在前面加0补充为两位数字
var m = myDate.getMinutes(); // 获取分
m = m > 9 ? m : "0" + m; // 如果分钟小于10,则在前面加0补充为两位数字
var s = myDate.getSeconds(); // 获取秒
s = s > 9 ? s : "0" + s; // 如果秒数小于10,则在前面加0补充为两位数字
time.innerHTML = h + " 时 " + m + " 分 " + s + " 秒 ";
}
}
</script>
</head>
<body>
<div class="calendar">
<p id="fulldate"></p>
<span id="nowdate"></span>
<strong id="saying"></strong>
<span>----- 今天的光阴 -----</span>
<div id="time"></div>
</div>
</body>
</html>
使用HTML
和CSS
,您可以创建一些漂亮的页面。但一旦了解了JavaScript
,您可以真正扩展您可以创建的页面类型。事实上,可能会开始把页面当作应用程序而不仅仅是页面。现在,如果您已经拥有JavaScript
,那么就有了一些未来的想法。然而,如果到目前为止主要使用HTML
和CSS
,应该知道学习编程语言有本质上的不同。对于HTML
和CSS
,所做的基本上是声明性的。例如,声明某些文本是一个段落,或者某"类选择器"
中的所有标记元素都应为红色
。而使用JavaScript
,您正在向页面添加行为,为此需要描述计算。需要能够描述操作DOM
或CSS
,达到页面逻辑
特殊行为和外观。要做到这些,需要一种与HTML
或CSS
截然不同的语言。它就是JavaScript
脚本编程语言。
熟悉了JavaScript
程序如何运行之后,接下来需要了解JavaScript
程序如何编写,本文的目的让您成为一个会编程的专业人士。要想写出程序,必须知道程序由哪些部分组成,即构成程序的最重要的三个部分分别是表达式
、变量
、语句
。
表达式是包含着值和运算的代码片段,并最终计算生成一个新值。下面给出了一些表达式的例子,以及其计算的新值:
表达式 计算值
3 ---> 3
3 + 4.2 * 6 ---> 28.2
(3 + 4.2) * 6 ---> 43.2
8 > 3 ---> true
8 > 3 && 1 === 2 ---> false
"hello" + "world" ---> "helloworld"
"world".length ---> 5
"world".replace("o","p") ---> "wprld"
[5,6,7,8,9].join("&") ---> "5&6&7&8&9"
(function(n){return n*6;})(9) ---> 54
所谓的值
(value),有数值
、文本值
和布尔值
(true
与false
)之分。数值对应数学的整数值及浮点数值;文本值要用一对双引号或单引号括起来;布尔值是关系运算
或逻辑运算
的结果,只有true
和false
两个值。
表示式可以包含多个运算符参与的运算,优先级高的运算符必须先计算。以下给出了JavaScript中常见运算符的优先级,从高到底排列,位于同一行的优先级相同。
优先级 运算符 说明
最高 ! 非
++ -- 一元自加、一元自减
* / % 乘、除、取模
+ - 加、减
< <= > >= 小于、小于等于、大于、大于等于
=== !== 等于、不等于
&& 与
最低 || 或
结合性规则用于在运算符的优先级相同时消除歧义。如果优先级有歧义,就使用括号
。
对于表达式求值得到的结果值
,需要将其放在一个容器
中保存起来,以备将来重用。而这个容器就是变量
,变量用于存储值
。
案例:
var persons = 3; // 此语句声明一个名为persons 的变量,并为其赋值3;
var name = "Tom"; // 这个语句为变量名分配一个字符串;
var isCapable = false; // 此语句将值false赋给变量isCapable。我们称true/false值为布尔值。注意:没有在布尔值周围加引号。
除了数字、字符串和布尔值之外,还有其他可以保存的值到变量,我们都以相同的方式创建所有变量。变量
就是一个带名字的容器,里面存放着值。让我们进一步了解一下如何声明变量:
var persons = 3; // 在声明变量时,我们总是以var关键字开头。
// var关键字之后,接下来为变量命名,这里是persons
// 可选地,我们通过在变量后面添加等号来为变量赋值。这个等号也称为赋值运算符
// 我们总是以分号";"结束赋值语句。
这里的命名变量也遵循了编程实践,那些保存固定不变值的变量,也称为常量
,全部使用大写字母命名;而通过输入获得值或者可能其值会改变的变量使用小写字母 。
作为可选的,因为如果需要,还可以创建一个没有初始值的变量,然后稍后为其赋值。要创建没有初始值的变量,只需省略赋值部分,如下所示:
var students // 通过省略等号和值,只需声明变量以供以后使用。
// 只声明变量但不给变量赋值,则其默认会取得一个特殊的值:undefined。
您知道变量有一个名字,也知道它们有一个值。还知道变量可以保存的一些东西是数字
、字符串
和布尔值
。但变量的名字不是随便起的,声明变量名的规则很简单,只需遵循以下两条规则即可创建有效的变量名:
_
)或美元符号($
)开始,之后,可以使用任意数量的字母、数字、下划线或美元符号。保留字
。JavaScript脚本要完整的构成,必须将表达式和变量连在一起组成语句
。表达式产生一个值,而语句代表一个操作。以下列语句为例:
var total = price - (price * (discount / 100));
/*
上面是一个JavaScript语句,它将将表达式求值赋值给变量total。
表达式中用到了乘法(*)和除法(/)以及减法(-)计算。
此表达式的计算结果是价格减去价格百分比的折扣。所以如果你的价格是10,折扣是20,那么得到8。
*/
脚本程序实际上就是一连串语句,这些语句在脚本运行时依次执行。这些语句包含下列操作:
true
)的情况下执行某个操作;true
)的情况下反复执行某个操作。前面的语句描述的脚本中只涉及前三种语句情况,下面针对后两种语句情况进行重点描述:
① 第四种语句情况:在条件为真(true
)的情况下执行某个操作。
清单 2:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>在条件为真(true)的情况下执行某个操作:if语句</title>
<script>
var scoops = 3; // 声明变量并赋初值
if (scoops >= 5) { //这是if关键字,后跟一个条件。这是一个有条件的测试,检查是否还有五个或更多勺。
alert("吃得快一点,冰淇淋快融化了!");
} else if (scoops == 3) { // 这是else if关键字,后跟一个条件。如果正好剩下三个。
alert("冰淇淋快用完了!");
} else if (scoops == 2) { // 这是else if关键字,后跟一个条件。如果正好剩下两个。
alert("去掉一勺!");
} else if (scoops == 1) { // 这是else if关键字,后跟一个条件。如果正好剩下一个。
alert("去掉两勺!");
} else if (scoops == 0) { // 这是else if关键字,后跟一个条件。如果正好剩下零个。
alert("一勺也没有了!");
} else { // 这是else关键字,上述条件均不成立,则执行此代码。
alert("还有很多冰淇淋,快来拿吧。");
}
</script>
</head>
<body>
</body>
</html>
清单2中使用了if语句
,它会根据你提供的条件,最多执行许多候选操作中的一种。这个语句的最一般的形式是有一个if部分
,0个或多个else if部分
,还可根据需要带有else部分
。每个候选项都是大括号中的语句序列。这些条件会自上而下依次判断。只要一个条件为真(true
),就会执行它对应的候选操作,然后结束整个if语句
。
清单2还可以通过另一种switch语句
来实现:
清单3 :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>在条件为真(true)的情况下执行某个操作:switch语句</title>
<script>
var scoops = 3; // 声明变量并赋初值
switch (scoops){
case 5:
alert("吃得快一点,冰淇淋快融化了!");
break;
case 3:
alert("冰淇淋快用完了!");
break;
case 2:
alert("去掉一勺!");
break;
case 1:
alert("去掉两勺!");
break;
case 0:
alert("一勺也没有了!");
break;
default:
alert("还有很多冰淇淋,快来拿吧。");
break;
}
</script>
</head>
<body>
</body>
</html>
清单3中的switch语句
,将一个值与一系列的case
进行比较,直到找出一个与它的值相等(===
)的case
,然后从该处开始执行语句。还可以根据需要包含一个default case
,它会匹配所有值。
其中的break
语句会终止整个switch语句
,每种case
都以一个break
结束。这是一种很好的做法,否则,执行会直落
到下一个case
。
② 第五种语句情况:在条件为真(true
)的情况下反复执行某个操作。
不止一次的去做同一件事情,当然,通常需要在代码中多次执行同一段代码块
,JavaScript
提供了几种在循环中重复执行代码的方法:while
、for
、for in
和forEach
。我们将研究这些循环方式。
while语句
,前面讨论的求值为布尔值的表达式
,这种类型的表达式是while语句
的关键。清单 4:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>在条件为真(`true`)的情况下反复执行某个操作:while语句</title>
<script>
var scoops = 8;
/* while语句以关键字while开头;
While使用一个布尔表达式,我们称之为条件测试,简称条件测试;
如果条件为真(true),则执行代码块中的所有内容;
什么是代码块?花括号之间的一切;即{}之间;
在执行代码块之后,返回条件测试。如果条件为真,并再次执行。如果条件为假,就完成了。
*/
while (scoops > 0) {
document.write("再来一勺!<br>");
scoops = scoops - 1;
}
document.write("没有冰淇淋的生活不一样!");
</script>
</head>
<body>
</body>
</html>
清单4中while语句
会在条件为真(true
)时重复执行代码,直到条件为假(false
)时,while语句
才会结束。
do while语句
的循环工作方式几乎与while语句
完全相同,只是循环体至少会执行一次,然后才进行条件测试
的判断。
清单 5:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>在条件为真(`true`)的情况下反复执行某个操作:do while语句</title>
<script>
var scoops = 8;
do {
document.write("要一勺!<br>");
scoops = scoops - 1;
} while (scoops > 0)
document.write("没有冰淇淋的生活不一样!");
</script>
</head>
<body>
</body>
</html>
清单5中do while语句
先执行一次循环体,然后在条件为真(true
)时重复执行循环体,直到条件为假(false
)时,do while语句
才会结束。
for语句
也是在条件为真(true
)时一直循环,但它通常用于迭代遍历一个固定的项目集,如一个数值范围
、一个字符串中的字符
、一个数组的索引
、一个对象链
等。
清单 6:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>在条件为真(`true`)的情况下反复执行某个操作:for语句</title>
</head>
<script>
/* 声明变量scores并将一个数组作为初值赋值给它;
数组会在后续内容讲解,通过new Array(数组大小),也可以通过中括号[]创建;
数组的索引编号从0开始,数组的长度通过它的属性length表示;最大索引号为:length-1;
*/
var scores = [
60, 50, 60, 58, 54, 54, 58, 50, 52, 54, 48, 69,
34, 55, 51, 52, 44, 51, 69, 64, 66, 55, 52, 61,
46, 31, 57, 52, 44, 18, 41, 53, 55, 61, 51, 44
];
var output; // 声明变量output
/* for语句的循环以关键字for开头。for右侧的圆括号内有三个部分,它们之间用";"分割。
第一部分是声明循环变量 i 并初始化,此初始化仅在for循环开始之前发生一次。
第二部分是条件测试。每次循环时,我们都会执行这个测试,如果它是假(false)错,我们就会停止。
第三部分是增加循环变量 i 计数的地方。它在循环体所有语句执行之后,每次循环都会发生一次。
*/
for (var i = 0; i < scores.length; i = i + 1) {
/* 每次通过循环,我们都创建一个字符串,编号值为i,获得的分数为scores[i]。
在这里将字符串拆分,使用字符串连接运算符(+)将字符串连在一起。
*/
output = "成绩编号 #" + i + " 分数: " + scores[i];
console.log(output); // 在控制台中显示字符串。
}
</script>
<body>
</body>
</html>
JavaScript包含一个用于迭代对象属性名的语句,即for in语句
。可以做到迭代器中的for
以任意顺序遍历对象中的每个属性。其将这一操作称为对象属性名的枚举。
清单 7:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>for in语句</title>
<script>
/* 声明变量car并将 一个对象作为初值赋值给它;
对象通过new Object(),也可以通过大括号{}创建;
对象的属性通过键-值方式,属性名和属性值之间通过":"分割,属性之间通过“,”分割。
*/
var car = {
make: '比亚迪',
model: '新能源',
year: '2022',
color: '黑色',
passengers: 5,
convertible: false,
mileage: 1021
};
/* 一次一个地遍历对象的属性,依次将每个属性分配给变量prop。 */
for (var prop in car) {
/* 可以使用prop作为中括号表示法访问属性值的方法 */
console.log(prop + ": " + car[prop]);
}
</script>
</head>
<body>
</body>
</html>
forEach
是JavaScript语言的ES5版本中数组对象
的一个方法,主要功能是遍历数组。
清单 8:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>forEach方法的使用</title>
<script>
var scores = [
60, 50, 60, 58, 54, 54, 58, 50, 52, 54, 48, 69,
34, 55, 51, 52, 44, 51, 69, 64, 66, 55, 52, 61,
46, 31, 57, 52, 44, 18, 41, 53, 55, 61, 51, 44
];
scores.forEach(function(value,index,array){
/* forEach方法中的function回调函数有三个参数:
第一个参数是遍历的数组内容,
第二个参数是对应的数组索引,
第三个参数是数组本身
*/
document.write("<br />成绩编号[" + index + "] 的成绩是" + value );
})
</script>
</head>
<body>
</body>
</html>
for of语句
是JavaScript语言的ES6版本中的对于集合对象
的遍历。
清单 9:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>for of语句</title>
<script>
var scores = [
60, 50, 60, 58, 54, 54, 58, 50, 52, 54, 48, 69,
34, 55, 51, 52, 44, 51, 69, 64, 66, 55, 52, 61,
46, 31, 57, 52, 44, 18, 41, 53, 55, 61, 51, 44
];
/* ES6通过关键字let声明变量score,迭代时将数组中的对应元素取出放入该变量中。 */
for(let [index,score] of scores.entries()) {
document.write("<br />成绩编号[" + index + "] 的成绩是" + score );
};
</script>
</head>
<body>
</body>
</html>
break语句
将立即终止整个循环。在搜索数组或集合对象时,当找到需要的数组元素内容或集合对象内的对象时,立即停止搜索,终止循环。
continue语句
将立即开始循环的下一次迭代,而不再完成当前的迭代。当循环体内满足某一条件时,不再执行循环体的后续代码,马上开始下一步循环。
清单 10:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>break语句与continue语句</title>
<script>
var scores = [
60, 50, 60, 58, 54, 54, 58, 50, 52, 54, 48, 69,
34, 55, 51, 52, 44, 51, 69, 64, 66, 55, 52, 61,
46, 31, 57, 52, 44, 18, 41, 53, 55, 61, 51, 44
];
for (var i = 0; i < scores.length; i++) {
if(scores[i] === 18 ){
document.write("<br />成绩18的编号是[" + i + "]" );
break; //终止当前的循环
}
}
for(let [index,score] of scores.entries()) {
if(score < 60){
continue; // 跳过小于60的成绩
}
document.write("<br />成绩编号[" + index + "] 的成绩是" + score );
};
</script>
</head>
<body>
</body>
</html>
程序由表达式
、变量
和语句
构成。其中表达式是对数据的运算,变量是对数据的存储,而语句是对数据处理的指令,也可说程序是由数据和处理数据的指令组成的
。这说明数据的重要性。在这里就来介绍程序操作的各种不同信息,不仅可以看到数值
、文本
(也称作字符串
)等原始形态的数据,也可以看到能够模仿现实中对象
的结构化数据。当您能够表达非常复杂的数据结构
,就可以编程复杂的程序脚本。
将数据进行分类,就是数据类型
。JavaScript实际上有六种数据类型,它们分别是布尔值
、数值
、字符串
、undefined值
、null值
、对象
。
布尔值只有两种值,分别是true
和false
,它们是它们是比较运算
和逻辑运算
的结果。
所谓的比较运算
。就是计算一个值是等于
(===
)、不等于
(!==
)、小于
(<
)、小于等于
(<=
)、大于
(>
)、还是大于等于
(>=
)另一个值。
所谓的逻辑运算
。对两个布尔值,使用x
和y
代表,可以执行与
(x && y
)、或
(x || y
)的操作;对一个布尔值,使用x
代表,可以执行非
(!x
)的操作。以下列出了三种逻辑运算符的各种组合结果:
x y x && y x || y !x
true true true true false
true false false true false
false true false true true
false false false false true
将比较运算
和逻辑运算
,组合在一个表达式中,该表达式称为布尔表达式
,其结果为布尔值。要注意的是这个布尔表达式中比较运算的优先级
高于逻辑运算。
数值
就是数学整数值和浮点数值。在JavaScript中进行以下描述。
适用于数值运算的操作符包括"加( +
)、减(-
)、乘(*
)、除(/
)和取模(%
)"。其中的取模运算是操作符(%
)对两个数相除后的余数。
针对数值还可以执行其它的数学运算,在JavaScript中提供了一个单例内置对象Math
,其内包含很多数学函数,可以进行操作数的特定计算。
数值受到计算设备固定大小的物理器件的限制,存在一个最大的数值(JavaScript中:这个值约为1.7910的308次方)和一个最小的数值(其值约为-1.7910的308次方)。任何计算得到的结果,其值大于最大数值,或小于最小数值,都会转化为一个特殊值Infinity
或-Infinity
。
数值除了存在大小的限制,还存在精度的限制。当计算无法得到精确表示的数值时,通过四舍五入换成最接近的数值。
NaN
代表的是非数值
(Not a Number
)。它在数学计算时得到非数学意义的结果时出现。NaN
不等于任何值,甚至不等于NaN
。要检测某个值是不是数值,可以使用isNaN
。
JavaScript中的非负整数也可以用十六进制表示。十六进制的计数规则是:0
、1
、2
、3
、4
、5
、6
、7
、8
、9
、A
、B
、C
、D
、E
、F
。如果想用十六进制表示整数,要在十六进制数值前加上0x
。
清单 11:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>用十六进制表示整数</title>
<script>
console.log(0x5); // 结果为 5
console.log(0xFF); // 结果为 255
console.log(-0xABCD); // 结果为 -43981
console.log(0xEF98); // 结果为 61336
</script>
</head>
<body>
</body>
</html>
执行清单11,可以到控制台查看结果。另外需要注意:不能用十六进制表示浮点数值,也不能使用科学记数法
。
所谓字符串
,就是一串字符。在JavaScript中,字符串要用一对双引号("
)或一对单引号('
)括起来,而且必须写在一行中。
字符
就是有名字的符号,比如键盘上的数字、字母、加号等。
符号
是字符的表现形式,比如符号∑
表示求和号,而符号♫
表示音乐。
字符集
由一组特定的字符组成,其中每个字符都有唯一的编号,称为编码
。JavaScript使用Unicode
字符集,它是用十六进制数值为每个字符编码,通过它们输出键盘上没有的字符,比如输出字符串"中国"
:
"\u4e2d\u56fd"
每个字符以\u
开头,后跟代表该字符编码的四位十六进制数字。\u
加编码的方式只在JavaScript代码中有效,若想在HTML页面文档中显示字符,则需要在编码两侧分别添加&#x
和分号;
。
清单 12:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Unicode编码在页面中显示</title>
</head>
<body>
<h1>中国</h1>
</body>
</html>
JavaScript支持很多字符串操作,通过其内置的库函数实现的。
清单 13:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>字符串操作</title>
<script>
console.log("ISchoolCode.cn".length); // 取字符串长度
console.log("ISchoolCode.cn".toLowerCase()); // 字符串转换为小写
console.log("ISchoolCode.cn".toUpperCase()); // 字符串转换为大写
console.log("ISchoolCode.cn".replace("ISchoolCode","爱校码")); // 替换
console.log("ISchoolCode.cn".charAt(7)); // 取索引为7位置的字符
console.log("ISchoolCode.cn".indexOf("de")); // 定位"de"的位置
console.log("ISchoolCode.cn".lastIndexOf("o")); // 定位最后的"o"的位置
console.log("ISchoolCode.cn".substring(7,11)); // 从当前字符串中取得从位置7到位置11的所有字符
console.log("ISchoolCode"+".cn"); // 连接两个字符串
</script>
</head>
<body>
</body>
</html>
字符串很重要的一个特性就是不可变性
,意思就是不能修改字符串中的字符,当然也不能改变字符串的长度。清单13中的执行只是对原字符串进行了操作输出,对原字符串没有任何影响,若要得到操作后的字符串,必须将其赋值给一个新变量
。
当有一个尚未初始化的变量,一个缺少属性的对象或一个缺少值的数组,最常见的是其值为undefined
。表示可能有,也可能没有,隐含着意外的空值。而 null
隐含着意料之中的空值,它是肯定和明确的。因此,声明一个变量时,进行初始化是必要的,即使初始化为空值时使用 null
,以避免undefined
。
JavaScript的所有非
布尔值、数值、字符串、null、undefined的值,都是对象
。对象将使您的JavaScript编程技能更上一层楼。它们是管理复杂代码、理解浏览器对象模型及文档对象模型(Browser Object Mode,简称BOM;Document Object Model,简称DOM)、组织数据的关键,甚至是许多JavaScript库打包的基本方式。
对象字面量
是一种定义新对象的表达式:
var dog = { // 为对象添加变量声明,接下来,用左花括号开始一个对象。
name: "爱米", // 然后,对象的所有属性都进入内部,每个属性都有一个名称、一个冒号和一个值。
breed: " 金毛犬", // 请注意,每个属性都用逗号分隔。
weight: 38
}; // 用右大括号结束对象,就像任何其他变量声明一样,用分号结束这个变量。
它只是属性的集合。从JavaScript数据类型的角度来考虑这些属性
,它们可以是布尔值、数值、字符串、null、undefined,也可以是对象、数组,甚至可以是函数。它们可以表示一个复杂的数据结构。这一切的结果是什么?当然是一个全新的对象。将对象视为将所有名称和值(换句话说,属性
)保存在一起的东西。
现在,得到了一个带有一组属性的活动对象。而且已经将对象分配给一个变量,可以使用该变量访问和更改其属性。
清单 14:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>对象的定义及操作</title>
<script>
/* 当一个对象被分配给一个变量时,该变量被赋予对该对象的引用。
它不“保存”对象本身。 将“引用”视为指向对象的指针。
*/
var dog = {}; // 一个没有属性的对象
dog.name = "爱米"; // 现在对象有一个属性
dog.breed = "金毛犬"; // 现在对象有两个属性
dog.weight = 38; // 现在对象有三个属性
dog.loves = "散步"; // 现在对象有四个属性
dog.bark = function(){ // 现在有一个新属性,它是一个函数
return "汪汪!";
}
console.log("狗名:"+dog.name);
console.log("狗种:"+dog.breed);
console.log("狗重:"+dog.weight);
console.log("狗悦:"+dog.loves);
console.log("狗吠:"+dog.bark());
</script>
</head>
<body>
</body>
</html>
运行清单14,打开浏览器的控制台,就可以看到结果了。
对象与其他五种值是不同的,它们统称为基本类型值
。对象与它们的区别主要表现在两方面:
对象表达式的值并非对象本身,而是一个指向对象的引用。
(引用可以理解为c语言中的指针。)对同一个对象字面量的每次求值,都会产生一个新对象。
另外,创建一个对象,不仅可以通过字面量
做到,而且还可以先创建一个对象的原型
(prototype
),称之为原型对象
,然后再基于这个原型对象创建其他对象。
清单 15:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>对象原型</title>
<script>
/* 定义一个圆形对象的原型,它的坐标x轴与y轴是(0,0),
其半径r为2,颜色c是透明。
*/
var protoObj = {
x: 0,
y: 0,
r: 2,
c: "transparent"
}
var obj1 = Object.create(protoObj); // 基于原型创建对象obj1,这是ES5定义的操作。
obj1.x = 5;
obj1.c = "red";
var obj2 = Object.create(protoObj); // 基于原型创建对象obj2。
obj2.y = 5;
obj2.r = 10;
console.log("对象obj1的x坐标:" + obj1.x); // obj1的自有属性
console.log("对象obj1的y坐标:" + obj1.y); // obj1的继承属性
console.log("对象obj1的半径:" + obj1.r); // obj1的继承属性
console.log("对象obj1的颜色:" + obj1.c); // obj1的自有属性
console.log("对象obj2的x坐标:" + obj2.x); // obj2的继承属性
console.log("对象obj2的y坐标:" + obj2.y); // obj2的自有属性
console.log("对象obj2的半径:" + obj2.r); // obj2的自有属性
console.log("对象obj2的颜色:" + obj2.c); // obj2的继承属性
</script>
</head>
<body>
</body>
</html>
数组是一种特殊的对象
,它可以保存许多值,可以将所有值视为一个整体,也可以在需要时访问各个分值。它的索引编号
是从0
开始的非负整数,而且有一个length
属性表示保存多少值的大小。
清单 16:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>匹配短语</title>
<script>
function makePhrases() {
var words1 = ["大家", "上午", "中午", "下午", "好"];
var words2 = ["你", "我", "他", "她", "他们", "我们"];
var words3 = ["吃饭", "睡觉", "跑步", "看书", "听音乐"];
var rand1 = Math.floor(Math.random() * words1.length);
var rand2 = Math.floor(Math.random() * words2.length);
var rand3 = Math.floor(Math.random() * words3.length);
var phrase = words1[rand1] + " " + words2[rand2] + " " + words3[rand3];
alert(phrase);
}
makePhrases();
</script>
</head>
<body></body>
</html>
实践中,我们会使用对象
描述一种具体的事物,会使用数组
描述一组事物。
函数
是一种执行特定计算的对象
。如果站在面向过程的语言的角度,如c语言
,函数就是子程序
,代表的是一个过程
;而子程序是一个大型程序中的某部分代码,由一个或多个语句块组成,它负责完成某项特定的任务,而且相较于其他的代码,具备相对的独立性。
从概念上,函数接受输入参数,进行计算,然后返回结果。像库函数,看不到其“内在工作”,可以将其想象成黑盒子
。
JavaScript在发展的过程中,尤其是前端开发的业务复杂度急剧上升,面向对象设计是解决复杂功能的主要方式,因此,坚持函数是特定对象这个理念。
在 JavaScript中,函数既然是特定对象,它属于对象数据类型。其类型值包含一个可执行的代码块,称为函数体
,以及零个或多个输入,称为形参
。
函数的定义有两种方式,一种是函数声明
的方式:
/* 带有function关键字、函数名bark、圆括号()、形参num和代码块{ }的标准函数声明。 */
function bark(num) {
for (var i = 0; i < num; i++) {
console.log("汪汪!");
}
}
/* 通过使用‘函数名’后跟圆括号来调用此函数,括号中包含任何所需的参数,称为实参。 */
bark(3);
上面的第一个语句是一个函数声明
,它创建了一个函数
,该函数的名称
为bark,可以用来引用和调用该函数。另一种函数定义是函数表达式
的方式:
/* 这看起来不太标准:函数没有名称,它位于变量赋值的右侧。
但有关键字function、圆括号()、形参num以及代码块{}
*/
var fly = function(num) {
for (var i = 0; i < num; i++) {
console.log("飞飞!");
}
};
/* 我们也可以调用这个函数,这次使用变量fly。*/
fly(3);
现在,当以这种方式使用 function
关键字时,在一个语句(如赋值语句
)中,我们将其称为函数表达式
。注意,与函数声明不同,此函数没有名称。此外,表达式会产生一个值,然后将该值分配给变量fly
。这个值是多少?将它分配给变量fly,然后稍后调用它,其值是对函数的引用
。
无论您使用函数声明还是函数表达式,都会得到相同的结果:函数
。那么有什么区别呢?声明是否更方便,或者函数表达式是否有用?还是这只是两种做同样事情的方法?乍一看,函数声明和函数表达式之间似乎没有太大区别。但是,实际上,这两者有着本质上的不同,为了理解这种差异,需要从查看浏览器在运行时如何处理代码开始。
浏览器
要做的第一件事是扫描
代码中的函数声明
。接下来,若在语句中有一个函数表达式
,这不是声明,浏览器继续前进(扫描
)。若遇到一个函数声明
,它需要解决这个问题,将做一个提升
的操作,它会创建一个函数,并将结果引用分配给与该函数同名
的变量。这时候,与函数同名的这个变量的作用域是全局的
,也意味着函数声明
方式定义的函数是全局的,其在代码中的前后位置无关紧要
。一直到扫描代码完毕。
接下来做什么?浏览器要执行代码。现在所有的函数声明都已经处理好了,浏览器会返回到代码的顶部并开始从上到下执行它。执行过程中,看到了一个函数表达式
,才开始创建一个函数,并将结果引用赋值给一个变量,例如前面定义的fly
。一旦fly变量被处理好,浏览器就会继续。若遇到函数声明
的代码,它在代码的第一次传递中已被处理,因此浏览器会跳过声明并转到后面的代码继续执行。
进一步执行中,在遇到了函数调用的代码。如果是对函数声明方式定义的函数调用,通过函数名,后跟圆括号和实参,是没有任何问题,函数已经被处理为全局作用域的。但当遇到变量fly
的调用,我们知道这是一个函数调用,因为我们使用的是变量名fly
,后跟圆括号和实参,记住fly
变量是对之前表达式函数
的引用。不过要记住的一点是:对变量fly
的调用代码一定是出现在函数表达式赋值之后。而对函数声明的函数名调用,出现在哪里都可以,即使出现在函数声明之前也是允许的,这是由浏览器的代码处理机制决定。
无论使用函数声明还是函数表达式定义函数,都会得到对该函数的引用:
清单 17:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>函数的定义及调用</title>
<script>
/* 函数声明定义,产生函数的引用,存储在与函数名同名的变量quack中 */
function quack(num) {
for (var i = 0; i < num; i++) {
console.log("呱呱!");
}
}
/* 函数表达式定义,产生函数的引用,存储在变量fly中 */
var fly = function(num) {
for (var i = 0; i < num; i++) {
console.log("飞!");
}
}
/* 将fly中的值分配给superFly之后,superFly保存函数引用,因此通过添加括号和参数,可以调用它! */
var superFly = fly;
superFly(2);
/* 尽管quag是由函数声明创建的,但quag中的值也是函数引用,因此可以将其分配给变量superQuack并调用它 */
var superQuack = quack;
superQuack(3);
</script>
</head>
<body>
</body>
</html>
清单 18:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> 将函数引用作为参数传递给函数</title>
<script>
/* 这是表示乘客的数据结构: */
var passengers = [{ // 所有乘客都保存在一个数组中
name: "张三", // 这里有四名乘客
paid: false
}, // 每个乘客都由一个带有姓名name属性和付费情况paid属性的对象表示。
{
name: "李四",
paid: true // paid属性是一个布尔值,表示乘客是否已支付航班费用。
},
{
name: "王麻子", // name属性是一个简单的文本字符串。
paid: true
},
{
name: "赵平原",
paid: true
}
];
/* 声明一个函数,检查禁飞名单
这是一个检查乘客是否已付款的功能。
*/
function checkPaid(passenger) {
if (!passenger.paid) {
return false;
}
return true;
}
/* 声明一个函数,检查每个乘客是否已付款
检查乘客是否在禁飞名单上的功能。禁飞名单很简单:除了张三,所有人都能飞。
如果乘客是张三,返回true;否则,返回false(即,乘客不在禁飞名单上)
*/
function checkNoFly(passenger) {
return (passenger.name === "张三");
}
/* 函数processPassengers有两个参数。第一个参数是passengers乘客数组。
第二个参数是一个函数,它知道如何查找乘客的某些情况。
*/
function processPassengers(passengers, func) {
for (var i = 0; i < passengers.length; i++) { // 一次遍历所有乘客
if (func(passengers[i])) { // 然后调用针对每个乘客的函数
return false; // 如果函数的结果为真,则返回false。换句话说,如
} // 果乘客没有通过测试,否则,就不希望飞机起飞。
}
return true; // 乘客通过了测试,返回true
}
/* 将函数传递给函数。我们只使用函数的名称作为参数。 */
var allCanFly = processPassengers(passengers, checkNoFly);
if (!allCanFly) {
console.log("飞机无法起飞:我们有一名乘客在禁飞名单上。");
}
/* 这里,传递checkPaid函数。因此,将检查每位乘客是否已付款 */
var allPaid = processPassengers(passengers, checkPaid);
if (!allPaid) { // 如果有乘客没有付钱,会返回false,将在控制台中看到此消息。
console.log("飞机不能起飞:不是每个人都付了钱。");
}
</script>
</head>
<body>
</body>
</html>
事件是在交互式Web页面如何用JavaScript来实现的功能,例如当按钮单击事件发生时,可能需要一个事件处理程序来对这个点击事件做出响应。
编写处理程序来处理事件。处理程序通常是一小段代码,它们知道事件发生时要做什么。就代码而言,处理程序只是一个函数
。当事件发生时,将调用其处理程序函数。要在事件发生时调用处理程序,首先需要注册它。举例一个当页面完全加载时生成的事件:当浏览器完全加载并显示页面中的所有内容(并构建表示页面的DOM)时,将触发页面加载事件。以下为解编写处理程序所需的步骤,并确保在触发页面加载事件时调用它:
① 首先,需要编写一个函数,在页面加载事件发生时处理它。
/* 处理程序只是一个普通函数。这里的函数,将其命名为pageLoadedHandler,
可以随意调用它。 请记住,我们通常将其称为处理程序或回调。
*/
function pageLoadedHandler() {
alert("我在这里!");
}
② 处理程序准备就绪,需要将其连接起来,以便浏览器知道在加载事件发生时应该调用一个函数。
/* 使用window对象的onload属性。
在load事件的情况下,将处理程序的名称分配给window对象的onload属性。
现在,当生成页面加载事件时,将调用pageLoadedHandler函数。
我们将看到不同类型的事件以不同的方式分配给处理程序。
*/
window.onload = pageLoadedHandler;
③ 浏览器将调用分配给window.onload的函数。
清单 19:
<!DOCTYPE html> <!--首先,浏览器加载页面,并开始解析HTML并构建DOM。 -->
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
/* 目前,脚本只定义了一个函数,并将该函数分配给window对象的onload属性。
请记住,当页面完全加载时,这个函数将被调用。
*/
window.onload = pageLoadedHandler; // 当它到达脚本时,浏览器开始执行代码。
function pageLoadedHandler() {
alert("我在这里!");
}
</script>
</head>
<body> <!-- 然后浏览器继续解析HTML。 -->
</body> <!-- 当浏览器解析完HTML,并且DOM准备就绪时,浏览器调用页面加载处理程序-->
</html>
博文最后更新时间: