第3章 获取用户的输入

上一章讲述了如何将JavaScript应用到HTML页面中,以及一些在Web页面的输出方法。其中的confirm函数不仅可以显示信息给用户,同时也可以接受简单的用户反馈。在常见的应用中,常常需要和用户进行更加复杂的交互,获取用户输入就显得不可或缺了。

本章知识点:

❑ 函数prompt的使用方法

❑ 基础知识:表达式和操作符

❑ 变量类型转换

❑ 字符串、转义符和字符串方法

3.1 示例:让用户输入两个数字,然后输出相加的结果

示例代码3-1.htm接受用户的两次输入,然后将输入的数字取整数部分相加,并用上一章节讲述的document.write方法输出到页面。

代码3-1.htm 让用户输入两个数字,然后输出相加的结果

01 <html>
02 <head>
03 <meta http-equiv="content-type" content="text/html; charset=GB2312" />
04 <title>3-1 让用户输入两个数字,然后输出相加的结果</title>
05 </head>
06 <body style="overflow:auto; padding:0px; margin:0px;">
07 <div style="font-size:14px; font-weight:bold; color:white; font-family:Arial, 宋体;
08 background-color:#6090DA; padding:4px 10px;">
09      <script>
10           intA = prompt("请输入第一个数字","");
11           intB = prompt("请输入第二个数字",27);
12           document.write("你输入的第一个数字是"+intA);
13           document.write("<br>你输入的第二个数字是"+intB);
14           document.write("<br>两者和是"+(parseInt(intA)+parseInt(intB)));
15      </script>
16 </div>
17 </body>
18 </html>

程序运行效果如图3.1和图3.2所示。

在代码3-1.htm中,可以看到prompt函数被用来获取用户的输入。该函数有两个参数,第一个是在要求输入时显示的提示信息,另一个是输入的默认值。该函数将用户的输入作为字符串返回。语法是:

strVariable = prompt("这里是显示的提示信息", "这里是默认的输入值");

返回的用户输入被保存在变量strVariable里。

图3.1 要求用户输入

图3.2 返回两次输入相加的结果

3.2 JavaScript基础知识—操作符和表达式

所有的高级计算机语言都有相似的逻辑结构,都是由数据和操作构成的。为了更好的表述编程中的各个概念,下面介绍一些编程术语。

3.2.1 什么叫表达式

对变量进行赋值、改变、计算等操作的语句叫做表达式。表达式是变量、常量和操作符的综合。一个表达式可以只包含一个常数或一个变量。操作符可以是四则操作符、关系操作符、位操作符、逻辑操作符、复合操作符。因此从类型上分,表达式可以分为算术表达式、字符操作表达式、赋值表达式和逻辑表达式等。

在书写上,JavaScript通常认为一个自然行是一个表达式。表达式的末尾通常使用分号“;”作为结束标志。实际上可以将所有的表达式写在一行上,用分号分隔开即可。但是出于可读性的考虑不推荐这样书写,除非几个语句都很短,而且在语意上并列(例如对若干变量的初始化赋值)。

表达式1
表达式2
/* 上面这样写是可以的 */
表达式1;             表达式2;         表达式3;
/* 上面这样书写也是符合语法的 */

3.2.2 什么叫操作符

操作符就是对数据进行操作的符号,其表达了要对数据执行的操作。表3.1是JavaScript中所有的操作符列表和说明。

表3.1 JavaScript的操作符

关于操作符的说明:

❑ 从参与操作的数据个数上看,操作符被分为一元操作符、二元操作符和三元操作符。一元操作符如自加(x++)、自减(x--),二元操作符最常见,如四则运算的加减乘除,三元操作符如条件操作符(c?x:y)。

❑ 三元条件操作符较复杂,这里举例讲解一下。

x=prompt("请输入一个正整数","10");
y=x>5?(x-5):(x*2);
alert(y);

首先用prompt函数从用户那里得到一个正整数。然后使用三元条件表达式做判断:x是否大于5?如果大于,x>5表达式的结果就是true(真),那么程序将执行“:”前面的表达式“x-5”,如果x小于5的话则执行“x*2”。最后,执行的结果(“x-5”或“x*2”)会被赋值给变量y,并用alert函数显示给用户。在程序中,一方面,条件表达式可以极大的缩减逻辑判断操作所需要的代码量;另一方面,反复堆叠的条件表达式,也会给代码的阅读带来一定困扰。因此条件表达式应当谨慎使用,并且不建议嵌套超过3次。

❑ 自加、自减操作符中,操作符与变量的相对位置,即“++x”和“x++”是不同的,需要仔细体会其运算的先后顺序。举例说明:

x=10;
y=x++;
z=++x;

那么运算后y和z的值分别是多少呢?y的值是10,z的值是12。原因请读者自己思考。

❑ 位运算符通常会被当作逻辑运算符来使用。此类运算符把两个操作数(即x和y)化成二进制数,对每个数位执行以上所列工作,然后返回得到的新二进制数。由于“真”值在电脑内部通常是全部数位都是1的二进制数,而“假”值则是全部是0的二进制数,所以位运算符也可以充当逻辑运算符。

❑ 逻辑与/或有时候被称为“快速与/或”。这是因为当第一操作数(x)已经可以决定结果时,y的值将不被计算。例如false&&y,因为x的值为false,不管y的值是什么,结果始终是false,于是该表达式立即返回false,而不去计算y是多少,甚至即使y导致出错,程序也可以照样运行下去。

❑ 与四则运算有关的运算符不可以作用在字符串上,但是可以使用“+”和“+=”来实现字符串的连接合并。“"a"+"b"”的运算结果是“"ab"”。

❑ 不要将赋值操作符“=”和逻辑操作符“==”混淆。一种常见的错误就是在需要比较两个操作数是否相等时误用了赋值操作符“=”,这种情况通常不会引发语法错误,而计算结果常常不符合预期,在调试程序时很难发现。

3.2.3 什么是优先级

在进行四则运算时,乘除法的计算顺序要优先于加减法,这就是表达式运算的优先级。3.2.2小节中表3.1各操作符按照优先级由高至低排列。在表达式中,具有高优先级的操作将被优先计算,然后才是优先级较低的操作符。如果若干并列的操作符具有相同的优先级,则按照自左至右的顺序计算。

和四则运算类似的是,括号可以用来改变运算的先后顺序,这在很多时候是至关重要的。在程序出错或者程序结果背离预期的时候,可以用括号来将复杂的表达式分解,强制按照要求的顺序来计算,常常可以解决很多异常。

善于利用优先级可以构造比较复杂的表达式,缩短代码长度。一般说来,只要表达式符合语法,即使看起来很“怪”也是可以运行的,例如:

x=y=z=v1==22?"v1 value is 22":((v1>22)?"v1 value is bigger than 22":"v1 value is smaller than 22");

这段代码就使用了嵌套条件表达式和多次赋值。

3.3 “一加一等于几?”变量类型转换

一加一看起来是个非常简单的问题,可是实际上在程序中,常常会出现程序员无法预料的各种状况。

【实例3.1】代码3-2.htm和前面的示例代码3-1.htm类似,试图计算用户两次输入的数字之和。

代码3-2.htm 计算用户两次输入的数字之和

01 <html>
02 <head>
03 <meta http-equiv="content-type" content="text/html; charset=GB2312" />
04 <title>3-2 一加一等于几?</title>
05 </head>
06 <body style="overflow:auto; padding:0px; margin:0px;">
07 <div style="font-size:14px; font-weight:bold; color:white; font-family:Arial, 宋体;
08 background-color:#6090DA; padding:4px 10px;">
09      <script>
10           intA = prompt("请输入第一个数字",1);
11           intB = prompt("请输入第二个数字",1);
12           document.write("你输入的第一个数字是"+intA);
13           document.write("<br>你输入的第二个数字是"+intB);
14           document.write("<br>两者和是"+(intA+intB));
15      </script>
16 </div>
17 </body>
18 </html>

图3.3 计算1+1时发生了意料外的结果

【代码说明】为什么程序会认为1+1=11?其实细心的读者应该会注意到,本章最初介绍prompt函数的时候说过,该函数会“将用户的输入作为字符串返回”。而且对于字符串来说,操作符“+”的含义并不是相加,而是将字符串连接起来。因此,在代码3-2.htm运行的时候,通过prompt获得的两次用户输入“1”被直接连接起来,得到运算结果“11”。

【运行效果】假设用户两次输入的数字都是1,程序运行的结果如图3.3所示。

在第2章中曾经提到过,JavaScript是一种弱类型语言。也就是说,不需要显式地声明各个变量的类型,JavaScript会自己决定变量在表达式中所扮演的“角色”。那么应该怎么解决变量类型的问题呢?表3.2是JavaScript内置的一些函数,用来实现变量类型的转换。

表3.2 用于转换变量类型的函数

比较代码3-1.htm和代码3-2.htm可以看出,代码3-1.htm使用parseInt将用户两次的输入转换为整形数值,并且用括号改变运算顺序,让数字相加的运算的操作优先执行。

【实例3.2】有时候,JavaScript自己决定变量类型也会产生出乎意料的错误。读者请阅读代码3-3.htm,并思考运行的结果是什么?

代码3-3.htm JavaScript自动类型转换

<html>
01 <head>
02 <meta http-equiv="content-type" content="text/html; charset=GB2312" />
03 <title>3-3 JavaScript自动类型转换</title>
04 </head>
05 <body style="overflow:auto; padding:0px; margin:0px;">
0 6 <div style="font-size:14px; font-weight:bold; color:white; font-family:Arial, 宋体;
07 background-color:#6090DA; padding:4px 10px;">
08      <script>
09           document.write("1+1的结果是"+1+1);
10           document.write("<br>3*3的结果是"+3*3);
11      </script>
12 </div>
13 </body>
14 </html>

图3.4 JavaScript自动类型转换

【代码说明】代码3-3.htm中,在计算1+1的时候,虽然两个常量都是整形的数值“1”,但是JavaScript按照操作符优先级相同时,自左至右的顺序,首先处理字符串“"1+1的结果是"+1”。JavaScript解释器认为这是字符串的连接,于是自动将常数“1”转变成了字符串类型。在计算3*3的时候,因为操作符“*”的优先级高于“+”,“3*3”的计算得以优先执行,于是得到了图3.4的结果。

【运行结果】运行的结果如图3.4所示。

3.4 JavaScript基础知识—字符串初探

在JavaScript中,字符串是一个非常重要的组成部分。这是因为为了要和用户交互,各种交互的文本信息都要用字符串来储存或处理。可以说,要想学好JavaScript,必须扎实地掌控字符串操作。JavaScript提供了非常强大的字符串处理功能。

3.4.1 什么是字符串

第2章在介绍数据类型的时候,已经做了简略说明:字符串就是以英文双引号“"”或单引号“'”括起来的一个或几个字符。要理解字符串的概念,就要理解以下几个方面的内容:

1)字符串中的信息只是一些文本。常常有初学者会把字符串中的信息和程序的代码混淆。下面的两行代码是不同的:

alert(today);
alert("today");

第一行的today只是一个变量,其内容可以是任何值。第二行的“today”才是字符串。

2)字符串不可以分行书写,引号中的内容必须书写在一行上。形如:

variable="This is a two line text
but it's forbidden"

这种书写格式是不符合语法的。

3)字符串的引号必须配对。也就是说,字符串的两端必须同时是双引号或单引号,不可以出现一端为双引号,另一端为单引号的情况。此外需要注意的是,字符串中不可以出现字符串两端的引号。例如,“"I said "yes"..."”是不符合语法的,而“"I said 'yes'..."”才是正确的写法。

4)字符串的引号必须是英文半角字符。很多初学者遇到的错误都是由于使用了中文的引号。

3.4.2 字符串的书写与转义符

当需要在字符串中使用引号或换行符等特殊字符时,需要使用转义符。转义符就是一些特殊组合的字符,用来代替那些因为语法问题无法书写的特殊字符。表3.3列出了常见的转义符及其含义。

表3.3 转义符及其含义

举例来说,如果想在字符串中包含引号,可以采用下面的方式:

variable="I said \"Yes\"....";

在转义符较多时,应注意反斜线的个数,以免出错。

3.4.3 字符串操作

在讲解字符串操作前,读者需要再次回忆JavaScript中“对象”的概念。在第2章中已经提及,JavaScript是基于对象的语言,因此JavaScript中的字符串也是一种对象,有着自己的属性和方法。

字符串对象的常用属性只有一个:length。该属性是指返回字符串对象的长度,即其包含的字符个数。语法为:

intStringLength="Some String".length;

字符串对象的方法有很多,见表3.4。

表3.4 字符串对象的方法

(续)

1)调用这些方法的语法类似于第2章中的Date对象。语法如下:

x="this is a string";              //x变量通过隐式声明为一个字符串对象
alert(x.length);                   //访问x的length属性并显示给用户
alert(x.toUpperCase());            //调用x的toUpperCase方法并将返回的结果显示给用户

2)这些方法中,fromCharCode方法比较特殊。其调用不是通过字符串对象的实例,而是通过内置对象String的原型来实现的,语法为:

x=String.fromCharCode(70);         //将unicode编码为70的字符赋值给x

3)字符串的match、replace和search用到了正则表达式对象。正则表达式是一种专为字符串处理设计的强力工具,在第9章中会有详细的讲述。

4)字符串的slice、substr和substring方法功能完全相同,参数稍有不同,使用时注意鉴别。这里的参数涉及“字符串中的位置”。字符串中的第一个字符位置为0,后继的字符位置依次加1。因此,字符串中最后一个字符的位置是字符串长度减1。需要注意的是,slice和substring函数在截取子字符串时,会返回start位置开始,到end位置之前的一个字符之间的子字符串。举例说明:

s_str="abcdefg".substring(1,4);

运行的结果,s_str的内容是“bcd”。

5)表格3-4中的方法并不会改变字符串对象本身,因此应使用变量接收方法的返回值进行操作。

【实例3.3】代码3-4.htm是一些基本的使用例子。

代码3-4.htm 字符串对象常用方法使用示例

01 <html>
02 <head>
03 <meta http-equiv="content-type" content="text/html; charset=GB2312" />
04 <title>3-4 字符串对象常用方法使用示例</title>
05 </head>
06 <body style="overflow:auto; padding:0px; margin:0px;">
07 <div style="font-size:14px; font-weight:bold; color:white; font-family:Arial, 宋体;
08 background-color:#6090DA; padding:4px 10px;">
09      <script>
10           document.write("big的效果".big());
11           document.write("<br>bold的效果".bold());
12           document.write("<br>fontsize=5的效果".fontsize("5"));
13           document.write("<br>A的Unicode编码是"+"A".charCodeAt(0));
14           document.write("<br>Unicode编码为70的字符是"+String.fromCharCode(70));
15           document.write("<br>Test toLowerCase".toLowerCase());
16           document.write("<br>Test toUpperCase".toUpperCase());
17      </script>
18 </div>
19 </body>
20 </html>

【代码说明】第10行是默认的字符串显示风格。第11~12行是更改了字体的显示风格。第13~16行是编码的使用效果。

【运行效果】程序运行效果如图3.5所示。

图3.5 字符串对象的方法应用举例

3.5 示例:让用户输入自己的名字,输出写给用户的情书

字符串方法具有强大和易用的特点,读者可从上文的例子中有所体会。下面的示例代码3-5.htm将综合前面讲述的内容,用prompt函数让用户输入自己的名字,然后通过对字符串的处理输出一封情书。

代码3-5.htm 让用户输入自己的名字,输出写给用户的情书

01 <html>
02 <head>
03 <meta http-equiv="content-type" content="text/html; charset=GB2312" />
04 <title>3-5 让用户输入自己的名字,输出写给用户的情书</title>
05 </head>
06 <body style="overflow:auto; padding:0px; margin:0px;">
07 <div style="font-size:14px; font-weight:bold; color:white; font-family:Arial, 宋体;
08 background-color:#6090DA; padding:4px 10px; text-indent:28px;">
09 <script>
10      var user_name, from_name, to_name;                  //声明变量
11 //将输入提示保存在变量中
12 var str_prompt="请输入你自己的名字和对方的名字,两个名字间用空格分开";
13 //将默认值保存在变量中
14 var str_prompt_default="自己的名字 对方的名字";
15      user_name=prompt(str_prompt, str_prompt_default);   //获取用户名
16      user_name=user_name?user_name:"小强 美眉";           //用户取消时的默认值
17      from_name=user_name.split(" ")[0];                  //分析写信者的名字
18      to_name=user_name.split(" ")[1];                    //分析收信者的名字
19      document.write(("<p>亲爱的"+to_name+"</p>").fontsize(3));   //开始写信
20          /*信件正文,替换掉文中的名称*/
21      document.write("<p>想到你那洒脱的笑容与动人的曲线,我禁不住提起笔,我选择这种原
22 始的方式来表达我对你的爱,希望你能接受。</p>".replace(/你/g,to_name+"你").replace(/我
23 /g,from_name+"我"));
24      document.write("<p>你在我心中的分量日益增加。你的眼,你的脸,你的笑容,悄悄地偷
25 走了我的心,在我闲暇时总有那种幻想的美...</p>".replace(/你/g,to_name+"你").replace(/我
26 /g,from_name+"我"));
27      /*信件结尾的签名*/
28      document.write(("<p>爱你的
29 "+from_name+"</p>").fontsize(2).fontcolor("gold").link("mailto:xiaoqiang@163.com"));
30 </script>
31 </div>
32 </body>
33 </html>

【运行效果】程序运行的结果如图3.6和图3.7所示。

图3.6 提示用户输入姓名

图3.7 输出处理后的情书

【代码说明】

1)程序用本章介绍的prompt函数来获取用户的输入。为了增进程序的易用性,程序设计为一次同时获得发信人和收信人的姓名(一次输入的用户体验要优于两次输入)。

2)prompt函数弹出的输入框有“确定”和“取消”两个按钮。用户在单击“确认”按钮时,文本输入框中的内容就被返回到程序中。那么当用户单击“取消”按钮时,prompt返回的值则是“空”,即JavaScript中的“null”。语句为:

user_name=user_name?user_name:"小强 美眉";

该语句的含义是,如果用户在要求输入的时候单击了“取消”按钮,那么user_name中的值就是“null”。而“null”在三元表达式中的作用等同于“false”,这时表达式就会把常数字符串“小强美眉”赋值给变量user_name。

需要特别注意的是,在编写程序的时候,最重要的步骤是在编写代码之前。在程序的功能设计和流程规划阶段,必须考虑到代码运行时可能出现的种种情况。这个阶段的一分仔细,可以节约调试阶段的十分努力。一种良好的习惯就是,在使用变量前,先对变量的内容做一个检查。这样可以避免输入异常造成的程序失败。

3)为了对用户输入的名字做分析,这里使用了字符串对象的split方法。如本章前面提到的,split返回一个数组,数组的元素是用split函数的参数分割字符串后形成的片段。引用数组元素的方法是使用中括号“[]”,中括号中的数字是需要引用的数组元素的位置。数组对象和字符串对象类似,数组元素的编号同样是从0开始编号的。

4)在书写情书的时候,使用了fontsize、fontcolor和link等函数实现输出的样式。link函数的参数是链接的地址。这里用来“mailto:”来实现Email的超链接。

5)函数replace中第一个参数“/我/g”是一个正则表达式的实例。其含义是,匹配字符串中所有的“我”这个字符。因此“replace(/我/g,from_name+"我")”这个操作的效果是,在字符串中所有的“我”前面加上用户输入的发信人名称。

3.6 小结

为了和用户更好的交互,需要获得用户的输入。在处理用户输入时,需要灵活使用JavaScript提供的强大的字符串操作方法。本章为入门者介绍了编程的一些术语:表达式和操作符。此外还讲解了变量类型及编程时容易犯的错误。

3.7 常见面试题分析

1. 简要描述出4个常用的转义符

❑ \b:退格符。

❑ \n:换行符。

❑ \r:回车。

❑ \t:制表符(Tab)。

2. 说出有关字符串大小写转换的函数名称和功能

❑ toLocaleLowerCase():返回字符串对象在本地编码系统中的小写形式。

❑ toLocaleUpperCase():返回字符串对象在本地编码系统中的大写形式。

❑ toLowerCase():返回字符串对象的小写形式。

❑ toUpperCase():返回字符串对象的大写形式。

3.8 本章习题

1.在JavaScript中,变量名“dog”和“Dog”是一个变量吗?为什么?

2.“a=b”与“a=b”这两条语句是一样的吗?

3. JavaScript使用什么来分隔两条语句?

4.定义几个标识符。

5.操作题:用JavaScript写一个带加减乘除运算的简易计算器。