导图社区 JavaScript网页编程从入门到精通(微课精编版)
JavaScript网页编程从入门到精通(微课精编版)配套
编辑于2020-10-22 20:44:37保守国家秘密法宣传教育,包含国家秘密的范围和密级、保密制度、 监督管理、 法律责任等。
为正确贯彻实施《中华人民共和国民法典》,统一法律适用,依法保护妇女、未成年人、老年人、残疾人的合法权益,维护婚姻家庭和谐稳定,推动家庭家教家风建设,本院结合审判实践起草了《最高人民法院关于适用<中华人民共和国民法典>婚姻家庭编的解释(二)(征求意见稿)》。为广泛听取社会各界意见,更好回应人民群众关切,现向社会公开征求意见。欢迎社会各界提出宝贵意见,并请在提出意见建议时说明具体理由。书面意见可寄往北京市东城区东交民巷27号,最高人民法院民事审判第一庭张灵若,邮编100745;电子邮件请发送至电子邮箱zgfmytlaw @163.com,本次征求意见截止日期为2024年4月30日。
诉讼费用交纳办法为现有规定,现已梳理,可快速检索查阅。包含诉讼费用交纳范围、 诉讼费用交纳标准、诉讼费用的负担、 司法救助等内容。
社区模板帮助中心,点此进入>>
保守国家秘密法宣传教育,包含国家秘密的范围和密级、保密制度、 监督管理、 法律责任等。
为正确贯彻实施《中华人民共和国民法典》,统一法律适用,依法保护妇女、未成年人、老年人、残疾人的合法权益,维护婚姻家庭和谐稳定,推动家庭家教家风建设,本院结合审判实践起草了《最高人民法院关于适用<中华人民共和国民法典>婚姻家庭编的解释(二)(征求意见稿)》。为广泛听取社会各界意见,更好回应人民群众关切,现向社会公开征求意见。欢迎社会各界提出宝贵意见,并请在提出意见建议时说明具体理由。书面意见可寄往北京市东城区东交民巷27号,最高人民法院民事审判第一庭张灵若,邮编100745;电子邮件请发送至电子邮箱zgfmytlaw @163.com,本次征求意见截止日期为2024年4月30日。
诉讼费用交纳办法为现有规定,现已梳理,可快速检索查阅。包含诉讼费用交纳范围、 诉讼费用交纳标准、诉讼费用的负担、 司法救助等内容。
JavaScript网页编程从入门到精通(微课精编版)
开篇:JavaScript基础
JavaScript构成
JavaScript核心(ECMAScript)
语法
类型
语句
关键字
保留字
操作符
对象
文档对象模型(DOM, Document Object Model)
W3C组织推荐的处理HTML或XML的标准编程接口,是一种与平台和语言无关的应用程序接口(API)。可以动态地访问程序和脚本,更新其内容、结构和样式
浏览器对象模型(BOM)
初次使用JavaScript
网页中嵌入JavaScript主要有4种方法
<script>标签:代码嵌入网页
<script>标签:加载外部脚本
事件属性:代码写入HTML标签的事件处理属性中,如onclick等。
事件属性 大部分HTML标签的事件属性(如onclick和onmouseover),可以允许写入JavaScript代码。当指定事件发生时,就会调用这些代码。例如: <div onclick="alert('Hello')"></div> 上面的事件属性代码只有一个语句。如果有多个语句,用分号分隔即可。
URL协议:URL支持以JavaScript协议的方式,执行JavaScript代码。
URL协议 URL支持javascript:协议,调用这个URL时,就会执行JavaScript代码。例如: <a href="javascript:alert('Hello')"></a> 浏览器的地址栏也可以执行javascipt:协议。将javascript:alert('Hello')放入地址栏,按回车键,就会跳出提示框。 如果JavaScript代码返回一个字符串,浏览器就会新建一个文档,展示这个字符串的内容,原有文档的内容都会消失。例如: <a href="javascript:new Date().toLocaleTimeString();"> 现在时间? </a> 在上面代码中,用户点击链接以后,会打开一个新文档,里面有当前时间。 如果返回的不是字符串,那么浏览器不会新建文档,也不会跳转。例如: <a href="javascript:console.log(new Date().toLocaleTimeString())"> 现在时间? </a> 在上面代码中,用户点击链接后,网页不会跳转,只会在控制台显示当前时间。 javascript:协议的常见用途是书签脚本Bookmarklet。由于浏览器的书签保存的是一个网址,所以javascript:网址也可以保存在里面,用户选择这个书签的时候,就会在当前页面执行这个脚本。为了防止书签替换掉当前文档,可以在脚本最后返回void 0。
编写脚本
使用<script>标签的方法一:直接在页面中嵌入JavaScript代码和包含外部JavaScript文件
【示例1】直接在页面中嵌入JavaScript代码。操作步骤如下。 (1)新建HTML文档,保存为test.html。然后在<head>标签内插入一个<script>标签。 (2)为<script>标签指定type属性值为"text/javascript"。现代浏览器默认<script>标签的类型为JavaScript脚本,因此省略type属性,依然能够被正确执行,但是考虑到代码的兼容性,建议定义该属性。 (3)直接在<script>标签内部输入JavaScript代码如右。 (4)保存网页文档,在浏览器中浏览。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>test</title> <script type="text/javascript"> function hi(){ document.write("<h1>Hello, World!</h1>"); } hi(); </script> </head> <body> </body> </html>
上面JavaScript脚本先定义了一个hi()函数,该函数被调用后会在页面中显示字符"Hello, World!"。document表示DOM网页文档对象,document.write()表示调用Document对象的write()方法,在当前网页源代码中写入HTML字符串"<h1>Hello, World!</h1>"。 调用hi()函数,浏览器将在页面中显示一级标题字符"Hello, World"。
使用<script>标签的方法二:包含外部JavaScript文件
【示例2】包含外部JavaScript文件。操作步骤如下。 (1)新建文本文件,保存为test.js。注意,拓展名为.js,它表示该文本文件是JavaScript类型的文件。 (2)打开test.js文本文件,在其中编写下面的代码,定义简单的输出函数。 function hi(){ alert("Hello, World!"); } (3)保存JavaScript文件,注意与网页文件的位置关系。这里保存JavaScript文件位置与调用该文件的网页文件位于相同目录下。 (4)新建HTML文档,保存为test1.html。然后在<head>标签内插入一个<script>标签。定义src属性,设置属性值为指向外部JavaScript文件的URL字符串,代码如下所示。 <script type="text/javascript" src="test.js"></script> (5)在上面<script>标签下一行继续插入一个<script>标签,直接在<script>标签内部输入JavaScript代码,调用外部JavaScript文件中的hi()函数。 (6)保存网页文档,在浏览器中预览。
提示:定义src属性的<script>标签不应再包含JavaScript代码。如果嵌入了代码,则只会下载并执行外部JavaScript文件,嵌入代码会被忽略。 <script>标签的src属性可以包含来自外部域的JavaScript文件。例如: <script type="text/javascript" src="http://www.sothersite.com/test.js"></script> 这些位于外部域中的代码也会被加载和解析。因此在访问自己不能控制的服务器上的JavaScript文件时要小心,防止恶意代码,或者防止恶意人员随时可能替换JavaScript文件中的代码。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>test</title> <script type="text/javascripte" src="test.js"></scripte> <scripte type="text/javascript"> hi(); //调用外部JavaScript文件中的hi()函数 </script> </head> <body> </body> </html>
JavaScript解析基础
JavaScript解析过程包括两个阶段:预处理(也称编译)和执行。在预编译期,JavaScript解释器将完成对JavaScript代码的预处理操作,把JavaScript代码转换成字节码;在执行期,JavaScript解释器把字节码生成二进制机械码,并按顺序执行,完成程序设计的任务。
浏览器与JavaScript
JavaScript主要寄生于Web浏览器中。
浏览器的核心包括两部分:渲染引擎和JavaScript解释器(又称JavaScript引擎)。
第1章:编写入门脚本代码
代码
<title>无标题文档</title> <script> document.write("<h1>Hello, World</h1>") </script> </head>
说明:<script>标签位置无限制。但要注意解析顺序。 一般在<head>标签里放公用函数;中间放全局变量;<body>标签下放置呈程序执行代码
说明
HTML为<script>定义了6个属性,简单说明:
async:可选。表示应该立即下载脚本,但不应妨碍页面中其他操作,如下载其他资源或等待加载其他脚本。该功能只对外部JavaScript文件有效。 charset:可选。表示通过src属性指定的代码的字符集。由于大多数浏览器会忽略它的值,因此很少使用。 defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。该属性只对外部JavaScript文件有效。IE'7及更早版本对嵌入的JavaScript代码也支持这个属性。 language:已废弃。原来用于表示编写代码使用的脚本语言,如JavaScript、JavaScript l.2或VBScript。大多数浏览器会忽略这个属性,不建议再使用。 src:可选。表示包含要执行代码的外部文件。 type:可选。可以看成是language的替代属性,表示编写代码使用的脚本语言的内容类型(也称为MIME类型)。虽然text/javascript和text/ecmascript已经不被推荐使用,但人们一直习惯使用text/javascript。服务器在传送JavaScript文件时使用的MIME类型通常是application/x-javascript,但在type中设置这个值可能导致脚木被忽略。另外,在非IE浏览器中还可以使用:application/javascript和application/ecmascript。考虑到约定俗成和最大限度的浏览器兼容性,目前在客户端,type属性值一般使用text/javascript。不过,这个属性并不是必需的,如果没有指定这个属性,则其默认值仍为text/javascript。
第2章:JavaScript基本语法
JavaScript遵循ECMA-262标准规范,并大量借鉴C语系语法特征。
编写第一行代码
JavaScript程序的执行以行(Line)为单位,即一行一行地执行。一般情况下,每一行就是一句话(语句),表示一条指令。语句(Statement)是为了完成某种任务而进行的操作。
语句以分号结尾,一个分号就表示一个语句,多个语句可以写在一行内。例如: var a=1+3;var b='abc'; 分号前面可以没有任何内容,JavaScript引擎将视为空语句。 ;;; //表示3个空语句。 表达式不需要分号结尾。一旦在表达式后面添加分号,则JavaScript引擎就将表达式视为语句,这样就会产生一些没有意义的语句。 1+3 'abc' //这两行语句有返回值,但没有任何意义,因为只返回一个单纯的值,没有其他任何操作。
JavaScript语法:指构成合法的JavaScript程序的所有规则和特征的集合
词法
定义了基本编码规则
字符编码规范
JavaScript程序使用Unicode字符集编写。Unicode字符集中每个字符使用两个字节来表示,这意味着用户可以使用中文来命名JavaScript变量。 <!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <script> var 人名 = "老张"; function 睡觉(谁){ alert(谁 + ":快睡觉!都半夜鸡叫了。"); } 睡觉(人名); </script> </head> <body> </body> </html> 【注意】 在第1、2版本中,ECMAScript标准只允许Unicode字符出现在注释,或者引号包含的字符串中,其他地方必须使用ASCII字符集。考虑到JavaScript版本的兼容性,以及开发习惯,不建议使用汉字来命名变量或函数名。 【提示】 由于JavaScript脚本一般都寄存在网页中,并最终由浏览器来解释,因此在考虑到JavaScript语言编码的同时,还要顾及嵌入页面的字符编码,以及浏览器支持的编码。一般建议保持页面字符编码与JavaScript编码一致,避免出现乱码。
命名规则
标识符(identifier)规范
变量名
函数名
参数名
属性名
合法的标识符命名应该注意如下几条规则,这些规则与C语系其他语言基本相同。
第一个字符必须是字母、下画线(_)或美元符号($)。
除了第一个字符外,其他位置字符可以使用字母、数字、下画线、美元符号。在ECMAScript v3中,用户可以使用完整的Unicode字符集来命名标识符,但是不建议使用。
标识符名称不能够与JavaScript关键字或保留字同名。
在ECMAScript v3版本中,可以在标识符中使用Unicode转义序列。例如,标识符a可以写成“\u0061”(Unicode转义序列),然后就可以在变量中使用这个转义序列代替字符本身。
【示例1】下面这两行代码中,先定义一个变量abc,变量abc中的a被转义序列表示,为变量abc初始化并在对话框中显示出来。 var \u0061bc = "标识符abc(变量)中a字符的Unicode转义序列是\\u0061"; alert(\u0061bc); 在书写时,转义序列不是很方便,一般很少这样使用,只有在特殊情况使用转义序列来传递或显示特殊字符,如JavaScript关键字、程序脚本等。 【注意】 JavaScript有一些保留字,不能用作标识符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。 另外,还有三个词虽然不是保留字,但是因为具有特别含义,也不应该用作标识符:Infinity、NaN、undefined。 【示例2】下面这些都是合法的标识符。 arg0 _tmp $elem π 【示例3】下面这些则是不合法的标识符。 1a // 第一个字符不能是数字 23 // 同上 *** // 标识符不能包含星号 a+b // 标识符不能包含加号 -d // 标识符不能包含减号或连词线 【示例4】中文是合法的标识符,可以用作变量名。 var 临时变量 = 1;
关键字规范
ECMA-262描述了一组具有特定用途的关键字,这些关键字可用于表示控制语句的开始或结束,或者用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。以下是ECMAScript的全部关键字,如表1所示。 表1 ECMAScript关键字 关键字 关键字 关键字 关键字 关键字 break delete function return typeof case do if switch var catch else in this void continue false instanceof throw while debugger finally new true with default for null try ECMA-262还描述了另外一组不能用作标识符的保留宇。保留字就是在目前还没有任何特定的用途,但它们有可能在将来版本中被用作关键字。 ECMAScript 5保留关键字: class、const、enum、export、extends、import、super 在严格模式下,下面关键字是保留字: implements、let、private、public、yield、interface、package、protected、static 在严格模式下,严格限制下面关键字用做变量名、函数名或参数名: arguments、eval ECMAScript 3将Java的所有关键字都列为保留字,但ECMAScript 5放宽了限制。 如果希望代码能在基于ECMAScript 3实现的解释器上运行的话,应当避免使用这些关键字作为标识符,如表2所示。 表2 ECMAScript 3保留字 保留字 保留字 保留字 保留字 保留字 abstract double goto native static boolean enum implements package super byte export import private synchronized char extends int protected throws class final interface public transient const float long short volatile JavaScript预定义了很多全局变量和函数,应当避免把它们的名字用做变量名和函数名,如表3所示。 表3 JavaScript预定义全局变量和函数 预定义 预定义 预定义 预定义 预定义 arguments encodeURL Infinity Number RegExp Array encodeURLComponent isFinite Object String Boolean Error isNaN parseFloat SyntaxError Date eval JSON parseInt TypeError decodeURL EvalError Math RangeError undefined decodeURLComponent Function NaN ReferenceError URLError JavaScript实现可能定义独有的全局变量和函数,每一种特定的JavaScript运行环境(客户端、服务器端等)都有自己的一个全局属性列表,这些都需要注意。
注释规则
注释就是不被解析的语句行或段。JavaScript把位于“//”字符后一行内的所有字符视为注释信息,从而忽略掉。 【拓展】 此外,由于历史上JavaScript兼容HTML代码的注释,所以<!--和-->也被视为单行注释。例如: x = 1; <!-- x = 2; --> x = 3; 上面代码中,只有x = 1会执行,其他的部分都被注释掉了。 注意,-->只有在行首,才会被当成单行注释,否则就是一个运算符。例如: function countdown(n) { while (n --> 0) console.log(n); } countdown(3) // 2 // 1 // 0 上面代码中,n --> 0实际上会当作n-- > 0,因此输出2、1、0。
JavaScript把位于“//”字符后一行内的所有字符视为注释信息,从而忽略掉。
【示例1】下面几条注释语句可以位于代码段的不同位置,分别描述不同区域代码的功能。 // 代码段前注释,概述代码段的功能 function toStr(a){ // 语句间注释,介绍函数 // 代码段中注释,区域代码功能描述 return a.toString(); // 语句结束后注释,语句作用描述 } 在使用单行注释时,在“//”符号后面的同一行内就不要输入任何代码,否则都被视为注释文本而忽略掉。
还可以使用“/*”和“*/”符号来包含多行注释信息。
【示例2】还可以使用“/*”和“*/”符号来包含多行注释信息。例如: /* 多行注释 多行注释 */ 在多行注释中,包含在“/*”和“*/”符号之间的任何文本都视为注释文本而忽略掉。
特殊字符用法
空格、制表符、换行符、换页符等在JavaScript程序中被统称为分隔符,用来分隔代码中的各种记号(如标识符、关键字、直接量、注释等信息),在解析时,JavaScript会忽略这些分隔符。
【示例1】对于下面代码块: function toStr(a){return a.toString();} 可以使用如下任意格式进行排版: function toStr(a){ return a.toString();} 或者: function toStr(a){ return a.toString(); } 或者: function toStr(a) { return a.toString(); } 用户可以根据阅读习惯格式代码显示。一般JavaScript编辑器也会提供代码格式化功能。 【拓展】 (1)分隔符虽然无实在意义,但是脚本中不能够缺少分隔符,特别是在标识符与关键字之间必须使用分隔符进行分隔,否则JavaScript会误认为它们是一个完整的标记而无法正确识别。 【示例2】在下面语句中,把关键字function与标识符toStr连在一起,以及把关键字return与toString标识符连在一起都是不正确的: functiontoStr(a){returna.toString();} // 错误写法 在它们之间必须使用分隔符进行分隔: function toStr(a){return a.toString();} // 正确写法 (2)JavaScript解析器一般采用最长行匹配原则,并在此基础上忽略代码中的分隔符。所谓最长行匹配原则,就是在一行内如果能够正确解析,那么就在一行内进行解析,否则会继续读取下一行代码,直到能够被正确解析为止。因此,用户不能够无节制地使用换行符。 【示例3】下面代码就会返回错误的信息。 function toStr(a){ return a.toString(); // 错误的换行 } alert(toStr("abc")); // 返回undefined 这是因为return作为一个独立语句,JavaScript解析器可以正确解析它,虽然它后面没有分号来标识该句的结束,但是解析器在正确解析的前提下,会自动为其补加一个分号,以表示该句已经结束。最后解析的脚本就变成了如下样式: function toStr(a){ return; a.toString(); } alert(toStr("abc")); // 返回undefined 出现这个错误的根源是因为分号不是JavaScript语句结束的唯一标志。很多时候,JavaScript会自动把换行符也看做是一句结束的标志。因此,当使用换行符时,应该防止类似错误的发生。上面代码的正确写法应该是: function toStr(a){ return a.toString(); } alert(toStr("abc")); // 返回字符串abc (3)不能在标识符、关键字等名称内插入分隔符,否则JavaScript会误认为它们是两个独立的标记并进行解析。 【示例4】在下面函数中,错误地使用空格把toString()方法分隔为两部分,则JavaScript会误认为它们是to关键字和String()自定义函数两个实词标记。 function toStr(a){ return a.to String(); // 错误分隔符 } (4)如果分隔符位于字符串或者正则表达式直接量内,则JavaScript会认为它们是具有一定语义的字符并进行解析。 【示例5】在下面代码中,变量a和b被赋予相同的字符串,但是变量b中间插入了空格,则比较结果发现它们是不相同的。 var a = "空格、制表符和换行符"; var b = "空格 、 制表符 和 换行符"; alert((a==b).toString()); // 返回false
句法
定义了JavaScript的逻辑范式,包括词、句和段的基本规则和特性。
词:词语用法
词,表示表达式。JavaScript句法中最小语义单位。
指令
变量
直接量
直接量(literal)是在程序中直接显示出来的值,如字符串、数值、布尔值、正则表达式、对象初始化、数组初始化等。 【示例】下面代码分别定义了字符串、数值、布尔值、正则表达式、特殊值、对象和数组直接量。 "字符串直接量" // 字符串直接量 123456 // 数值直接量 true // 布尔值直接量 /^ab.*/g // 正则表达式直接量 null // 特殊值直接量 {a:1,b:2} // 对象初始化直接量 [1,2] // 数组初始化
运算符
表达式
在JavaScript中,词语之间必须使用分隔符进行分隔,否则JavaScript就会错误解析。
【示例6】下面代码块是一个简单的求两个数的平均值方法。 var a = 34; var b = 56; function aver(c,d){ return (c+d)/2; } alert(aver(a,b)); 其中var、function、return是指令,这些指令也是JavaScript默认的关键字。a、b、c、d、aver、alert为变量,34、56是数值直接量,=、(、)、{、}、/、+、,是运算符。
句:句式用法
句,表示语句,一行执行特定任务的命令。 句子就是由词构成的完整的可执行命令。在JavaScript中,常用分号(;)来划分句子,有时候也可以省略分号,此时会使用换行符表示完整的句子。 一个句子可以包含一个或多个词 【示例2】在下面两个句子中,第一个句子只有一个词,这是一个指令词,该指令只能够位于循环体内或switch结构体内。第二个句子包含3个分词,alert函数名,小括号表示运算符,而“"提示信息"”表示字符串直接量。 break; // 单个词构成一个句子 alert("提示信息"); // 多个词构成一个句子 一个句子也可以包含一个或多个段落 【示例3】在下面句子中,直接调用一个匿名函数。 (function(i){ // 一个段落结构构成一个句子 alert(i); })("提示信息"); // 调用函数,返回“提示信息”弹出信息 【示例4】可以把函数包含在另一个函数中形成嵌套结构,这个嵌套结构体就构成了一个复杂的句子。 (function(i){ // 闭包结构 return function(){ // 向闭包结构返回一个函数 alert(i); }; })("提示信息")(); // 调用闭包函数,返回“提示信息”弹出信息 句子也可以什么都不包含,仅由一个分号进行标识,这样的句子称之为空句子,空句子常用做占位符。 【示例5】在下面这个循环体内就包含了一个空句子。 for(var i; i<100;i++){ ; // 空句子 }
段:逻辑结构的基本规则和特性
段,包含多行命令的逻辑结构。
在JavaScript程序中,常用大括号来划分段落结构,大括号拥有封装代码和逻辑的功能,由此形成一个独立的段落结构。 JavaScript使用大括号将多个相关的语句组合在一起,称为“区块”(block)。 与大多数编程语言不一样,JavaScript的区块不构成单独的作用域(scope)。也就是说,区块中的变量与区块外的变量,属于同一个作用域。 { var a = 1; } a // 1 上面代码在区块内部,声明并赋值了变量a,然后在区块外部,变量a依然有效,这说明区块不构成单独的作用域,与不使用区块的情况没有任何区别。所以,单独使用的区块在JavaScript中意义不大,很少出现。区块往往用来构成其他更复杂的语法结构,比如for、if、while、function等。
声明变量使用var语句
声明var多为局部变量
//【示例1】可以在声明中为变量赋值。未赋值的变量,则初始值为underfined var a; //声明但没有赋值 var b=1; //声明并赋值 alert(a); //返回underfined alert(b); //返回1 var a,b,c //声明多个变量 var a=b=c=1 //声明多个变量并赋值
一个语句中,可以同时声明多个变量,这时应该使用逗号运算符分隔多个变量名。 在JavaScript中,可以重复声明同一个变量,也可以反复初始化变量的值。 var a=1; var a=2; var a=3; alert(a); //返回3 var语句声明的变量是JavaScript标准声明变量的方法,同时使用var语句声明的变量是永久的,不能够使用delete运算符删除。 【示例】var语句的使用范围有限,不能在循环或条件语句的表达式中使用。例如,下面两种用法都是错误的。 while(var i=0,(i++)<10){ alert(i); } if(var i=false){ alert(i); } 但是,可以在for或for-in语句的条件表达式中使用。例如: for(var i=0;i<10;i++){ alert(i); } for(var i in document){ alert(i); }
不声明直接为变量赋值(即自动隐式声明变量):但隐式声明的变量总是作为全局变量
定义全局变量有3种方式
在任何函数外面使用var语句声明
var f='value'
直接添加一个属性到全局对象上。在Web浏览器中,全局对象为window
window.f='value'
直接使用未经声明的变量,以这种方式定义的全局变量被称为隐式的全局变量
f='value'
赋值变量
使用等号(=)运算符可以为变量赋值,等号左侧为变量名,右侧为值或可以转换为值的表达式。
JavaScript引擎的工作方式是,在预编译期先解析代码,获取所有被声明的变量,然后在执行期再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫作变量提升(Hoisting)。
<script> //【示例】 var a=1; //全局变量 (function(){ var b=2; //第1层局部变量 (function(){ var c=3; //第2层局部变量 (function(){ var c=4; //第3层局部变量 alert(a+b+c+d); //返回10 })() //直接调用函数 })() //直接调用函数 })() //直接调用函数 <script>
变量的作用域(Scope)也称为可见性:指变量在程序中可访问的有效范围
全局作用域:指变量在整个页面脚本中都可见,对应变量为全局变量。
在函数体内使用全局变量是一种很危险的行为,应该养成在函数体内使用var语句声明局部变量的习惯。
函数作用域:指变量仅能在声明的函数内部可见,函数外是不允许访问的。有时也成为局部作用域,对应变量为局部变量。
概要
1变量的优先级
var a=1; //全局变量 (function f(){ var a=2; //局部变量 alert(a); //返回2 })(); //直接在函数体上调用函数
var a=1; //全局变量 function f(a){ //参数变量 alert(a); //返回3 })(3); //直接调用函数,并传递参数值为3
var a=1; //全局变量 (function f(a){ //参数变量 var a=2; //局部变量 alert(a); //返回2 })(3); //直接调用函数,并传递参数值为3
2局部作用域嵌套
var a=1; //全局变量 (function(){ var a=2; //第1层局部变量 (function(){ var a=3; //第2层局部变量 (function(){ var a=4; //第3层局部变量 alert(a); //返回4 })() //直接调用函数 })() //直接调用函数 })() //直接调用函数
6种基本数据类型
null
空值。表示无值,即此处的值就是“无”的状态
undefined
未定义。表示不存在,由于目前没有定义,所以此处暂时没有任何值
一般看成两个特殊值
number
数值。整数和小数,如1和3.14
string
字符串。字符组成的文本,如“Hello World”
boolean
布尔值。true(真)和false(假)两个特定值
称为原始类型(Primitive Type)的值,即不能再细分。
object
对象。各种值组成的集合
狭义的对象(Object)
数组(Array)
两种不同的数据组合方式
函数(Function)
将对象称为合成类型(Complex Type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。
使用typeof运算符可以检测数据类型,它以字符串的形式返回上述6种基本类型之一
alert(typeof 1); //返回字符串“number” alert(typeof"1"); //返回字符串“string” alert(typeof true); //返回字符串“boolean” alert(typeof {}); //返回字符串“object” alert(typeof []); //返回字符串“object” alert(typeof function(){}); //返回字符串“function” alert(typeof null); //返回字符串“object” alert(typeof undefined); //返回字符串“undefined”
注意:typeof运算符有两个特殊的返回值:把null标识为Object类型,把function(){}标识为Function类型。 【示例】由于type null返回字符串为"object",要有效检测JavaScript基本数据类型,可以自定义一个type方法,解决基本类型的区分问题。 function type(o){//返回值类型数据的类型字符串 return(o===null)?"null":(typeof o); //如果是null值,则返回字符串"null",否则返回(typeof o)表达式的值 } 上面代码可以有效避免开因为null值影响基本数据的类型检测
数值(Number)/数字
JavaScript不细分整型、浮点型,所有数值都属于浮点数。
数值直接量
当数值直接出现在程序中时,被称为数值直接量。在JavaScript程序中,直接输入的任何数字都被视为数值直接量。 【示例1】数值直接量可以细分为整型直接量和浮点型直接量。浮点数是带有小数点的数值,而整数是不带小数点的数值。 var int=1; //整型数值 var float=1.0; //浮点型数值 整数一般都是32位数值,而浮点数一般都是64位数值。 【示例2】浮点数可以使用科学计数法来表示。 var float=1.2e3; 等价于 var float=1.2*10*10*10; 或 var float=1200;
八进制
八进制数值直接量以数字0为前缀,其后跟随一个八进制的数值
var num=0764; //八进制数值 alert(num); //返回500 注意:考虑到安全性,不建议使用八进制数值直接量,因为JavaScript可能会误解析为十进制数值。
十六进制
十六进制数值直接量以“0X”或“0x”作为前缀,后面跟随十六进制的数值。十六进制的数值是从0~9和a~f的数字或字母任意组合,用来表示0~15之间的某个数字,超过这个范围则以进制表示
var num=0x1F4; //十六进制数值 alert(num); //返回十进制值为500
数值运算
使用算术运算符,可以参与各种计算,如加、减、乘、除等。
JavaScript内置Math对象,该对象提供大量数学方法,直接调用这些方法可以解决专业数学计算问题,详细说明请参考JavaScript参考手册。
特殊数值
Infinity
无穷大。当数值超过浮点型所能够表示的范围。反之,负无穷大为-Infinity
NaN
非数值。不等于任何数值,包括自己。如0除以0的返回值
Number.MAX VALUE
最大值
Number.MIN VALUE
最小值,一个接近0的数值
Number.NaN
非数值,与NaN相同
Number.POSITIVE_INFINITY
正无穷大
Number.NEGATIVE_INFINITY
负无穷大
字符串(String)/文本
JavaScript不细分字符串和字符。
字符串直接量
Unicode字符
数字
各种符号
字符串必须包含在单引号或双引号之中
如果字符串包含在双引号中,则字符串内可以包含单引号。反之,可以在单引号中包含双引号。
字符串应在一行内显示,换行显示是不允许的。如果需要字符串换行显示,可以在字符串中添加换行符(\n)。例如 alert("字符串\n直接量"); //在字符串中添加换行符
alert("字符串 直接量"); //提示错误
在字符串中添加特殊字符,需要转义字符表示,如单引号、双引号等。
字符串中每个字符都有固定的位置。首字符的下标位置为0,第2个字符的下标位置为1,以此类推。这与数组元素的位置一样,最后一个字符的下标位置是字符串长度减1。
转义序列
在特殊语境中,无法直接使用字符自身。例如,在字符串中包含说话内容。 "子曰:"学而不思则罔,思而不学则殆。"" 由于JavaScript已经赋予了双引号为字符串直接量的声明符号,如果在字符串中包含双引号,就会破坏字符串的直接量。解决方法必须使用转义表示。 "子曰:\"学而不思则罔,思而不学则殆。\""
\ 0
Null字符(\u0000)
\b
退格符(\u0008)
\t
水平制表符(\u0009)
\n
换行符(\u000A)
\v
垂直制表符(\u000B)
\f
换页符(\u000C)
\r
回车符(\u000D)
\"
双引号(\u0022)
\'
单引号(\u0027)
\\
反斜线(\u005C)
\xXX
由两位十六进制数值XX指定的Latin-1字符
\uXXXX
由4位十六进制数值XXXX指定的Unicode字符
\XXX
由1~3位八进制数值指定的Latin-1字符。ECMAScript 3.0版本不支持,一般不建议使用
JavaScript定义反斜杠加上字符可以表示字符自身。但一些字符加上反斜杠后会表示特殊含义,这些特殊转义字符被称为转义序列,它是字符的一种间接表示方法。 由于反斜杠具有转义功能,但它仅对特殊字符有转义功能,因此当在一个正常字符前添加反斜杠时,JavaScript会忽略该反斜杠。
字符串操作
使用加号(+)运算符可以连接两个字符串
alert("学而不思则罔"+"思而不学则殆");
使用length属性可以返回字符串的字符长度
alert("学而不思则罔,思而不学则殆".length); //返回13
调用String对象的方法,可以做复杂的字符串操作,如果配合正则表达式,还可以实现字符串的智能操作
布尔值(Boolean)
true:真
false:假
注意:在JavaScript中,undefined、null、""、0、NaN和false这6个特殊值转换为逻辑值时都为false,被俗称为假值。除了假值之外,其他任何类型的值转换为逻辑值时都是true,如空数组([])和空对象({})对应的布尔值,都是true。
Null和Undefined
注意,JavaScript的标识符区分大小写,所以undefined和null不同于Undefined和Null(或者其他仅仅大小写不同的词形),后者只是普通的变量名。
null是Null型的直接量,表示空值。
默认转为0
undefined是undefined类型的直接量,表示未定义的值。当声明变量未赋值时,或者属性未设置值时,默认值均为undefined。
默认转为NaN
运算符
大部分JavaScript运算符用标点符号表示,如“+”和“=”,也有几个运算符由关键字表示,如delete和instanceof。JavaScript定义了51个运算符。
JavaScript定义了51个运算符,详细说明如表2.1所示。 【提示】 下表各列说明如下: 优先级:表示运算符参与运算的先后顺序。数字越大,运算优先级就越高;数字相等,则运算等级相同,将根据位置决定运算优先顺序。 操作类型:表示运算符所要操作的数据类型。 运算顺序:表示运算符操作对象的方向,如从左到右或从右到左。 表2.1 JavaScript运算符 运算符 说明 优先级 操作类型 运算顺序 .(点号) 读写对象的属性 15 对象.标识符 从左到右 [](中括号) 数组下标 15 数组[整数] 从左到右 ()(小括号) 调用函数 15 函数(参数) 从左到右 new 创建新对象 15 构造函数调用 从右到左 ++(连加) 先递增或后递增运算 14 变量、对象的属性、数组的元素 从右到左 --(连减) 先递减或后递减运算 14 变量、对象的属性、数组的元素 从右到左 -(减号) 一元减法运算(或取负、取反) 14 数字 从右到左 +(加号) 一元加法运算 14 数字 从右到左 ~(否定号) 按位取反操作 14 整数 从右到左 !(叹号) 逻辑取反操作 14 布尔值 从右到左 delete 删除对象的一个属性定义 14 变量、对象的属性、数组的元素 从右到左 typeof 返回数据类型 14 任意 从右到左 void 返回未定义的值 14 任意 从右到左 *(星号) 乘法运算 13 数字 从左到右 /(斜杠) 除法运算 13 数字 从左到右 %(百分号) 取余数运算(或称之为取模运算) 13 数字 从左到右 +(加号) 加法运算 12 数字 从左到右 -(加号) 减法运算 12 数字 从左到右 +(加号) 连接字符串操作 12 字符串 从左到右 << 左移 11 整数 从左到右 >> 带符号右移 11 整数 从左到右 >>> 不带符号右移 11 整数 从左到右 < 小于 10 数字、字符串 从左到右 <= 小于等于 10 数字、字符串 从左到右 > 大于 10 数字、字符串 从左到右 >= 大于等于 10 数字、字符串 从左到右 instanceof 检查对象类型 10 对象 构造函数 从左到右 in 检查一个属性是否存在 10 字符串 in 对象 从左到右 == 比较是否相等 9 任意 从左到右 != 比较是否不相等 9 任意 从左到右 === 比较是否等同(同值同类) 9 任意 从左到右 != = 比较是否不等同(不同值同类) 9 任意 从左到右 &(连字符) 按位与操作 8 整数 从左到右 ^(顶角符号) 按位异或操作 7 整数 从左到右 |(竖线符号) 按位或操作 6 整数 从左到右 && 逻辑与操作 5 布尔值 从左到右 || 逻辑或操作 4 布尔值 从左到右 ?: 条件运算符(包含3个运算数) 3 布尔值?任意:任意 从右到左 =(等号) 赋值运算 2 变量、对象的属性、数组的元素=任意 从右到左 *= 附带乘法操作的赋值运算 2 变量、对象的属性、数组的元素*=任意 从右到左 /= 附带除法操作的赋值运算 2 变量、对象的属性、数组的元素/=任意 从右到左 %= 附带取余操作的赋值运算 2 变量、对象的属性、数组的元素%=任意 从右到左 += 附带加法操作的赋值运算 2 变量、对象的属性、数组的元素+=任意 从右到左 -= 附带减法操作的赋值运算 2 变量、对象的属性、数组的元素-=任意 从右到左 <<= 附带左移操作的赋值运算 2 变量、对象的属性、数组的元素<<=任意 从右到左 >>= 附带带符号右移操作的赋值运算 2 变量、对象的属性、数组的元素>>=任意 从右到左 >>>= 附带不带符号右移操作的赋值运算 2 变量、对象的属性、数组的元素>>>=任意 从右到左 &= 附带按位与操作的赋值运算 2 变量、对象的属性、数组的元素&=任意 从右到左 ^= 附带按位异或操作的赋值运算 2 变量、对象的属性、数组的元素^=任意 从右到左 |= 附带按位或操作的赋值运算 2 变量、对象的属性、数组的元素|=任意 从右到左 ,(逗号) 多重计算操作 1 任意 从左到右
一元运算符:一个运算符仅对一个运算数执行某种运算,如值取反、位移、获取值类型、删除属性定义等。
二元运算符:一个运算符必须包括两个运算数。例如,两个数相加,两个值比较。大部分运算符都是对两个运算数执行运算。
三元运算符:一个运算符必须包含三个运算数。JavaScript仅有的一个三元运算符(?:运算符),该运算符就是条件运算符,它是if语句的简化版。
运算符的使用
使用算术运算符
加法运算(+)
【示例1】特殊运算数的运算结果比较特殊,需牢记
var n=5; //定义并初始化任意一个数值 alert(NaN+n); //返回NaN。NaN与任意运算符相加,结果都是NaN alert(Infinity+n); //返回Infinity。Infinity与任意运算数相加,结果都是Infinity alert(Infinity+Infinity); //返回Infinity。Infinity与Infinity相加,结果是Infinity alert((-Infinity)+(-Infinity)); //返回-Infinity。负Infinity相加,结果是-Infinity alert((-Infinity)+(Infinity)); //返回NaN。正负Infinity相加,结果是NaN
【示例2】加运算符能够根据运算数的数据类型,尽可能地把数字转换成可以执行相加或相连接运算的数值或字符串
alert(1+1); //返回2。如果运算数都是数值,则进行相加运算 alert(1+"1"); //返回"11"。如果运算数中有一个是字符串,则把数值转换为字符串,然后进行相连运算 alert("1"+"1"); //返回"11"。如果运算数都是字符串,则进行相连运算
【示例3】下面两个表达式,由于空字符串的位置不同,运算结果也是不同。在第一行代码中,3.0和4.3都是数值类型,因此加号运算符就执行相加运算,由于第3个运算数是字符串,则把第1个加号运算结果转换为字符串并与空字符串进行相连操作,而第2行代码中则不同,第1个相加号运算符首先把数值3.0转换为字符串,然后执行相连运算,所以结果也就不同。
alert(3.0+4.3+""); //返回“7.3” alert(3.0+""+4.3); //返回“34.3”
减法运算(-)
【示例1】特殊运算数的运算结果比较特殊,需牢记。
var n=5; //定义并初始化任意一个数值 alert(NaN-n); //返回NaN。NaN与任意运算数想减,结果都是NaN alert(Infinity-n); //返回Infinity。Infinity与任意运算数相减,结果都是Infinity alert(Infinity-Infinity); //返回NaN。Infinity与Infinity相减,结果是NaN alert((-Infinity)-(-Infinity)); //返回NaN。负Infinity相减,结果是NaN alert((-Infinity)-Infinity); //返回-Infinity。正负Infinity相减,结果是-Infinity
【示例2】在减法运算中,如果有一个运算数不是数字,则返回值为NaN;如果数字为字符串,则会把它转换为数值之后,再进行运算。
alert(2-"1"); //返回1 alert(2-"a"); //返回NaN
【示例3】对于字符串"100aaa"而言,parseFloat()方法能够解析出前面几个数字,而对于减法运算符来说,则必须是完整的数字时,可以进行完全匹配转换。
alert(parseFloat("100aaa")); //返回100 alert(parseFloat("aaa100")); //返回NaN alert("100aaa"-0); //返回NaN alert("100"-0); //返回100
乘法运算(*)
【示例】特殊运算数的运算结果比较特殊,需留意。
var n=5; //定义并初始化任意一个值 alert(NaN*n); //返回NaN。NaN与任意运算数相乘,结果都是NaN alert(Infinity*n); //返回Infinity。Infinity与任意非0正数相乘,结果都是Infinity alert(Infinity*(-n)); //返回Infinity。Infinity与任意非0负数相乘,结果都是-Infinity, //换句话说结果的符号由第二个运算数的符号决定 alert(Infinity*0); //返回NaN。Infinity与0相乘,结果是NaN alert(Infinity*Infinity); 返回Infinity。Infinity与Infinity相乘,结果是Infinity
除法运算(/)
【示例】特殊运算数的运算结果比较特殊,需留意。
var n=5; //定义并初始化任意一个值 alert(NaN/n); //返回NaN。如果某个运算数是NaN,结果都是NaN alert(Infinity/n); //返回Infinity。Infinity被任意数字除,结果都是Infinity或-Infinity, //符号由第二个运算数的符号决定 alert(Infinity/Infinity); //返回Infinity。0除一个非无穷大的数字,结果是Infinity或-Infinity, //符号由第二个运算数的符号决定 alert(n/0); //返回-Infinity。参考上一行注释说明
余数运算符/模运算(%)
就是求余数
alert(3%2); //返回余数1
模运算主要针对整数执行操作,但是它也适用浮点数
alert(3.1%2.3); //返回余数0.8000000000000003
特殊运算数的运算结果比较特殊,需留意
var n=5; //定义并初始化任意一个数值 alert(Infinity%n); //返回NaN alert(Infinity%Infinity); //返回NaN alert(n%Infinity); //返回5 alert(0%n); //返回0 alert(0%Infinity); //返回0 alert(n%0); //返回NaN alert(Infinity%0); //返回NaN
数值取反运算符(-):是一元运算符,或称一元减法运算符
【示例】特殊运算数的取反运算结果
alert(-5); //返回-5。正常数值取负数 alert(-"5"); //返回-5。先转换字符串数字为数值类型 alert(-"a"); //返回NaN。无法完全匹配运算,返回NaN alert(-Infinity); //返回-Infinity alert(-(Infinity)); //返回Infinity alert(-NaN); //返回NaN
递增(++)和递减(--)运算:是通过不断加1或减1以实现改变自身值的一种快捷运算方法
递增运算符和递减运算符是一元运算符,只能够作用于变量、数组元素或对象属性,这是因为在运算过程中会执行赋值运算,赋值运算左侧必须是一个变量、数组元素或对象属性,只有这样赋值才得以实现。 【示例】下列代码是错误用法。 alert(4++); //返回错误 下面代码是正确的用法。 var n=4; alert(n++); //返回4
递增运算符和递减运算符有位置讲究,位置不同所得运算结果也不同。它们在运算之前都会试图转换值为数值类型,如果失败则返回NaN。
【示例1】先执行赋值运算,再执行递加运算。即先计算表达式的返回值,最后才把自身值递加 var n=4; alert(n++); //返回4 先执行递加运算,再返回表达式的值 var n=4; alert(++n); //返回5
【示例2】每个表达式与变量n的值并非都同步 var n=4; alert(n++); //返回4 alert(++n); //返回6。在递加之前,变量n的值是5,而不是4
使用逻辑运算符
逻辑运算与布尔值紧密联系,也称布尔代数。所谓布尔代数就是布尔值(true和false)的“算术”运算。逻辑运算常与比较运算结合使用,在条件表达式中经常使用。
与运算(&&)
实际上就是两个运算数的AND布尔操作,只有当两个条件都为true时,它才返回true,否则返回false,是一种短路逻辑。详细描述如表
与运算符(&&)的逻辑解析: 首先,计算第一个运算数,即左侧表达式。如果左侧表达式的计算值可以被转换为false(如null、0、underfined等),那么就会结束计算,直接返回第一个运算数的值。 然后,当第一个运算数的值为true时,则将计算第二个运算数的值,即位于右侧的表达式,并返回这个表达式的值。 【示例】下面代码利用逻辑与运算检测变量初始值。 var user; //定义变量 (!user && alert("没有赋值")); //返回提示信息“没有赋值” 逻辑与运算符 第一个运算数的布尔值 第二个运算数的布尔值 逻辑与运算结果 true true true true false false false true false false false false
或运算(||)
当或运算符左右两侧运算数的值都是布尔值时,则它将执行布尔OR操作。如果两个运算数的值为true,或者其中一个为true,那么它就返回true,否则就会返回false。详细描述如表
对于与(&&)和或(||)运算符来说,它们不会改变运算数的数据类型,同时也不会强制逻辑运算的结果是什么数据类型,它们的特性是:
在逻辑运算时,与和或运算都会把运算数视为布尔值,即使不是布尔值,也将对其进行转换,然后根据布尔值执行下一步的操作。
逻辑与(&&)和逻辑或(||)运算并非完整地执行所有运算数,它们可能仅执行第一个运算数,从而忽略第二个运算数。
非运算(!)
非运算符是一元运算符,直接放在运算数之前,将对运算数执行布尔取反操作(NOT),并返回布尔值
【示例1】如果对于运算数执行两个逻辑非运算操作,实际上它相当于把运算数转换为布尔值数据类型
alert(!5); //返回false。把数值5转换为布尔值,并取反 alert(!!5); //返回true。把数值5转换为布尔值 alert(!0); //返回true。把数值0转换为布尔值,并取反 alert(!!0); //返回false。把数值5转换为布尔值
提示:逻辑与和逻辑或运算符所执行的操作返回的未必都是布尔值,但是对于逻辑非运算符,它的返回值一定是布尔值。
【示例2】特殊的运算数的逻辑非运算返回值
alert(!{}); //返回false。如果运算数是对象,则返回false alert(!0); //返回true。如果运算数是0,则返回true alert(!(n=5)); //返回false。如果运算数是非0的任何数字,则返回false alert(!null); //返回true。如果运算数是null,则返回true alert(!NaN); //返回true。 alert(!Infinity); //返回false。 alert(!(-Infinity)); //返回false。 alert(!undefined); //返回true。
使用关系运算符/比较运算符
它反映了运算数之间关系的一类运算,因此这类运算符一般都是二元运算符,关系运算返回的值总是布尔值。
大小比较
比较运算中的运算数不局限于数值,可以是任意类型的数据,但是在执行运算时,它主要根据数值的大小,以及字符串中字符在编码表中的位置来比较大小。所以对于其他类型的值,将会被转换为数字或字符串,然后再进行比较。
<
第一个运算数小于第二个运算数,比较运算的返回值为true。否则为false
<=
第一个运算数小于等于第二个运算数,比较运算的返回值为true。否则为false
>=
第一个运算数大于等于第二个运算数,比较运算的返回值为true。否则为false
>
第一个运算数大于等于第二个运算数,比较运算的返回值为true。否则为false
运算数的转换操作规则说明
如果运算数都是数字,或者都可以被转换成数字,则将根据数字大小进行比较
alert(4>3); //返回true,直接利用数值大小进行比较 alert("4">Infinity); //返回false,无穷大比任何数字都大
运算数虽然都可以被转换为数字,但由于它们都是字符串,则不再执行数据类型转换,而是直接根据字符串进行比较
alert("4">"3"); //返回true,以字符串进行比较,而不是数字大小进行比较
运算数都是字符串,或者都被转换为字符串,那么将根据字符在字符编码表中的位置大小进行比较。同时字符串是区分大小写的,因为大小写字符在表中的位置不同。一般小写字符大于大写字符。如果比较中不区分大小写,则建议使用toLowerCase()或toUpperCase()方法把字符串统一为小写或大写形式。
alert("a">"b"); //返回false,字符a编码为61,字符b编码为62 alert("ab">"cb"); //返回false,c的编码为63。从左到右对字符串中对应字符逐个进行比较 alert("abd">"abc"); //返回true,d的编码为64。前面字符相同,则比较下一个字符
如果一个运算数是数字,或者被转换为数字,另一个是字符串,或者被转换为字符串,则比较运算符调用parseInt()将字符串强制转换为数字,不过对于非数字字符串来说,将被转换为NaN值,最后以数字方式进行比较。运算数是NaN,则比较结果为false。
alert("a">"3"); //返回true,字符a编码为61,字符3编码为33 alert("a">3); //返回false,字符a被强制转换为NaN
如果运算数都无法转换为数字或字符串,则比较结果为false。
如果一个运算数为NaN,或者被转换为NaN,则始终返回false。
如果对象可以被转换为数字或字符串,则执行数字或字符串比较。
包含检测
in运算符能够判断左侧运算数是否为右侧运算数的成员。其中左侧运算数应该是一个字符串,或者可以转换为字符串的表达式;右侧运算数应该是一个对象或数组。
等值检测
==(相等)
比较两个运算数的返回值,看是否相等
!=(不相等)
比较两个运算数的返回值,看是否不相等
===(全等)
比较两个运算数的返回值,看是否相等,同时检测它们的数据类型是否相等
!==(不全等)
比较两个运算数的返回值,看是否不相等,同时检测它们的数据类型是否不相等
遵循的基本规则
相等运算
如果运算数是布尔值,在比较之前先转换为数值。其中false转为0,true转换为1。
如果一个运算数是字符串,另一个运算数是数字,在比较之前先尝试把字符串转换为数字。
如果一个运算数是字符串,另一个运算数是对象,在比较之前先尝试把对象转换为字符串。
如果一个运算数是数字,另一个运算数是对象,在比较之前先尝试把对象转换为数字。
如果两个运算数都是对象,那么比较它们的引用值(引用地址)。如果指向同一个引用对象,则相等,否则不等。
特殊运算数的相等比较
alert("1"==1); //返回true。字符串被转换为数字 alert(true==1); //返回true。true被转换为1 alert(false==0); //返回true。false被转换为0 alert(null==0); //返回false alert(undefined==0); //返回false alert(undefined==null); //返回true alert(NaN=="NaN"); //返回false alert(NaN==1); //返回false alert(NaN==NaN); //返回false alert(NaN!==NaN); //返回true
NaN与任何值都不相等,包括它自己。null和undefined值相等,但它们是不同类型的数据。在相等比较中,null和undefined是不允许被转换为其他类型的值。
全等运算
如果运算数都是值类型,则只有数据类型相同,且数值 相等时才能够相同。
如果一个运算数是数字、字符串或布尔值(值类型),另一个运算数是对象等引用类型,则它们肯定不相同。
如果两个对象(引用类型)比较,则比较它们的引用地址。
特殊运算数的全等比较
alert(null===undefined); //返回false alert(0==="0"); //返回false alert(0===false); //返回false
var a={}; var b=a; alert(a===b); //由于它们都引用相同的地址,所以返回true
var a={}; var b={}; alert(a===b); //虽然它们的结构相同,由于地址不同,所以返回false
使用赋值运算符
简单赋值运算符(=)
简单的赋值运算符,就是把右侧的运算数的值直接赋值给左侧变量
符加操作的赋值运算符
就是赋值之前还要对右侧运算数执行某种操作,然后再复制,详细说明如表
+=
加法运算或连接操作并赋值
示例a+=b
转化为a=a+b
-=
减法运算并赋值
a-=b
a=a-b
*=
乘法运算并赋值
a*=b
a=a*b
/=
除法运算并赋值
a/=b
a=a/b
%=
取模运算并赋值
a%=b
a=a%b
<<=
左移位运算并赋值
a<<=b
a=a<<b
>>=
右移位运算并赋值
a>>=b
a=a>>b
>>>=
无符号右移位运算并赋值
a>>>=b
a=a>>>b
&=
位与运算并赋值
a&=b
a=a&b
|=
位或运算并赋值
a|=b
a=a|b
^=
位异或运算并赋值
a^=b
a=a^b
赋值运算符的左侧运算数必须是变量、对象属性或数组元素。
使用对象操作运算符
主要指对对象、数组、函数执行特定任务操作的一组运算符,主要包括in、instanceof、new、delete、.(点号)、[](中括号)和()(小括号)运算符
使用位运算符
逻辑位运算符
位与(&)
位或(|)
位异或(^)
位非(~)
逻辑位运算:与逻辑运算符的运算方式相同,但是针对的对象不同。逻辑位运算符针对的是二进制的整数值,而逻辑运算符针对的是非二进制的其他类型数据
移位运算符
左移(<<)
右移(>>)
无符号右移(>>>)
移位运算:是对二进制值进行有规律移位,移位运算可以设计很多奇妙的效果,这在图形图像编程中应用比较广泛
位运算
认识位运算
是整数的逐位运算。JavaScript中,位运算要求运算数必须是32位整数,如果位运算数是非整型,或者大于32位的整数,则将返回NaN。
使用其他运算符
条件运算符
条件运算符与条件语句在逻辑上相同。但条件运算符侧重于连续运算,它自身可以作为表达式,也可以作为子表达式使用;而条件语句侧重于逻辑结构,在结构中执行不同的运算。条件运算符拥有函数式特性,而条件语句具有面向对象的编程结构。
是JavaScript唯一的三元运算符,语法形式如下: a?x:y
其中a、x、y是它的3个运算数。a运算数必须是一个布尔型的表达式,即返回值必须是一个布尔值,一般使用比较表达式来表达。x和y是任意类型的值。如果运算数a返回值为true时,将执行x运算数,并返回该表达式的值。如果运算数a返回值为false时,将执行y运算数,并返回该表达式的值。
【示例】定义变量a,然后检测a是否被赋值,如果赋值则使用该值,否则使用默认值给它赋值。 var a; //定义变量a a?(a=a):(a="Default Value"); //检测变量a是否赋值 alert(a); //显示变量a的值 条件运算符可以转换为条件语句: var a; if(a) //赋值 a=a; else //没有赋值 a="default value"; alert(a); 条件运算符也可以转换为逻辑表达式如下。 var a; a&&(a=a)||(a="default value"); //逻辑表达式 alert(a); 在上面表达式中,如果a为true,则执行(a=a)表达式,执行完毕就不再执行逻辑或运算符后面(a="default value")表达式;如果a为false,则不再执行逻辑与运算符后面的(a=a)表达式,同时将不再继续执行逻辑或运算符前面的表达式a&&(a=a),转而执行逻辑或运算符后面的表达式(a="default value")。
逗号运算符
是二元运算符,它能够先执行运算符左侧的运算符,然后再执行右侧的运算符,最后仅把右侧运算数的值作为结果返回
void运算符
是一元运算符,它可以出现在任意类型的运算数之前,执行运算数,却忽略运算数的返回值,结果总返回一个undefined。void多用于URL中执行JavaScript表达式,但不需要表达式的计算结果
表达式
严格模式
使JavaScript在更严格的条件下运行。
案例实战
转换为字符串
将值转换为字符串是编程中常见行为。
使用加号运算符
当值与空字符串相加运算时,JavaScript会自动把值转换为字符串
把数字转换为字符串
把布尔值转换为字符串,返回字符串"true"或"false"。
把数组转换为字符串,返回数组元素列表,以逗号分隔
把函数转换为字符串,返回函数结构的代码字符串
对象直接量,则返回字符串为"[object object]"
如果是自定义类的对象实例,则返回字符串为"[object object]"。
如果是内置对象实例,具体返回字符串必须根据传递的参数而定
使用toString()方法
当为原始值调用toString()方法时,JavaScript会自动把它们装箱为对象。然后再调用toString()方法,把它们转换为字符串。
转换为数字
JavaScript提供了两种静态函数把非数字的原始值转换为数字
parseInt()可以把值转换为整数
alert(parseInt("123abc")); //返回数字123 alert(parseInt("1.73")); //返回数字1 alert(parseInt(".123")); //返回值NaN
在开始转换时,parseInt()函数会先查看位置0处的字符,如果该位置不是有效数字,则将返回NaN,不再深入分析;如果位置0处的字符是数字,则将查看位置1处的字符,并进行同样的测试,依此类推,在整个验证过程中,直到发现非数字字符为止,此时parseInt()函数将把前面分析合法的数字字符转换为数值,并返回。 浮点数中的点号对于parseInt()函数来说是属于非法字符的,因此不会转换它,并返回。
var d=010; //八进制数字字符串 var e="0x10"; //十六进制数字字符串 alert(parseInt(d)); // 返回十进制数字8 alert(parseInt(e)); //返回十进制数字16
如果以0为开头的数字,则parseInt()函数会把它作为8进制数字处理,先把它转化为数值,然后再转换为10进制的数字返回,如果以0x为开头的数字字符串,则parseInt()函数会把它作为16进制数字处理,先把它转化为数值,然后再转换为10进制的数字返回。
var a="123abc"; alert(parseInt(a,16)); //返回值十进制整数1194684
parseInt()也支持基模式,可以把二进制、八进制、十六进制等不同进制的数字字符串转化为整数。基模式由parseInt()函数的第2个参数指定。
alert(parseInt("10",2)); //把二进制数字10转换为十进制整数为2 alert(parseInt("10",8)); //把八进制数字10转换为十进制整数8 alert(parseInt("10",10)); //把十进制数字10转换为十进制整数为10
下面代码把二进制、八进制和十进制数字似乎转转换为整数。
alert(parseInt("010")); //把默认基数字010转换为十进制整数为10 alert(parseInt("010",8)); //把八进制数字010转换为十进制整数为8 alert(parseInt("010",10)); //把十进制数字010转换为十进制整数为10
如果第1个参数是十进制的值,包含0前缀,为了避免被误解为8进制的数字,则应该指定第2个参数值为10,即显式定义基,而不是采用默认基。
parseFloat()可以把值转换为浮点数
parseFloat()函数与parseInt()函数用法基本相同。
alert(parseFloat("1.232.5")); //返回数值1.234
它能够识别第一个出现的小数点号,而第二个小数点号被视为非法的。
alert(parseFloat("123")); //返回数值123 alert(parseFloat("123abc")); //返回数值123 alert(parseFloat("010")); //返回数值10 alert(parseFloat("0x10")); //返回数值0 alert(parseFloat("x10")); //返回数值NaN
数字必须是十进制形式的字符串,不能够使用八进制或十六进制的数字字符串。同时对于数字前面的0(八进制数字标识)会忽略,对于十六进制形式的数字,则返回0值。
对字符串类型的值有效,其他类型的值调用这两个函数都会返回NaN
使用乘号运算符
var a=a; //数值 var b="1"; //数字字符串 alert(a+b); //返回字符串"1"
加号运算符不仅能够执行数值求和运算,还可以把字符串连接起来,由于JavaScript处理字符串连接操作的优先级要高于数字求和运算。因此,当数字字符串与数值使用加号连接时,将优先执行连接操作,而不是求和运算。 在执行表达式a+b的运算时,变量a先被转化为字符串,然后以求和进行计算,所以计算结果为字符串"11",而不是数值2。因此,我们常常使用加号运算符把一个值转化为字符串。 不过,如果让变量b乘以1,则加号运算符就以求和进行计算。 如果让一个数字字符串变量乘以1,则JavaScript解释器能够自动把数字字符串转换为数值,然后再继续求和运算,而不是进行字符串连接操作。
var a=1; //数值 var b="1"; //数字字符串 alert(a+(b*1)); //返回数值2
转换为数字形式字符串
Number拓展了toString()方法,允许传递一个整数参数,该参数可以设置数字的显示模式。数字默认为十进制显示模式,通过设置参数可以改变数字模式。
如果采用默认模式,则toString方法会直接把数值转换为数字字符串
var a=1.000; var b=0.0001; var c=1e-4; alert(a.toString()); //返回字符串"1" alert(b.toString()); //返回字符串"0.0001" alert(c.toString()); //返回字符串"0.0001"
toString()方法能够直接输出整数和浮点数,保留小数位。小数位末尾的零会被清除。但是对于科学计数法,则在条件许可的情况下把它转换为浮点数,否则就使用科学计数法方式输出字符串。 var a=1e-14; alert(a.toString()); //返回字符串"1e-14" 在默认模式下,无论数值采用什么模式,toString()方法返回的都是十进制的数字。因此,对于八进制、二进制或十六进制数值,toString()方法都会先把它们转换为十进制数值之后再输出。 var a=010; //八进制数值10 var b=0x10; //十六进制数值10 alert(a.toString()); //返回字符串"8" alert(b.toString()); //返回字符串"16"
如果设置参数,则toString()方法会根据参数把数值转换为对应进制的值之后再输出
var a=10; //十进制数值10 alert(a.toString(2)); //返回二进制数字字符串"1010" alert(a.toString(8)); //返回八进制数字字符串"12" alert(a.toString(16)); //返回二进制数字字符串"a"
toFixed()
能够把数值转换为字符串,并显示小数点后的指定位数。
var a=10; alert(a.toFixed(2)); //返回字符串"10.00" alert(a.toFixed(4)); //返回字符串"10.0000"
toExponential()
不采用科学记数法,但是toExponential()方法专门用来把数字转换为科学记数法形式的字符串。 指定了保留的小数位数。省略的部分采用四舍五入的方法进行处理。
var a=123456789; alert(a.toExponential(2)); //返回字符串"1.23e+8" alert(a.toExponential(4)); //返回字符串"1.2346e+8"
toPrecision()
toPrecision()与toExponential()方法不同,它是特定有效数字的位数,而不仅仅是指小数位数。
var a=123456789; alert(a.toPrecision(2)); //返回字符串"1.2e+8" alert(a.toPrecision(4)); //返回字符串"1.235e+8"
使用toString()方法把数值转换为字符串时,无法保留小数位,这在货币格式化、科学记数等专业领域输出显示数字是不方便的。从1.5版本开始,JavaScript定义了3个新方法:toFixed()、toExponential()和toPrecision()。
转换为对象
把对象转换为值
对象在逻辑运算环境中的转换
对象在数值运算环境中的转换
数组在数值运算环境中的转换
对象在模糊运算环境中的转换
强制类型转换
Boolean(value):把参数值转换为boolean型
Number(value):把参数值转换为number型
String(value):把参数值转换为string型
第3章 JavaScript程序结构设计
语句
语句之间通过分号分隔,当一个表达式单独一行显示时,JavaScript会自动补加分号。任何表达式加上分号,就是表达式语句。 空语句:就是包含没有任何代码的句子,它只有一个分号(;),表示该语句的结束。 ; //空语句 空语句不会执行任何操作,相当于一个占位符 【示例】在循环结构中使用空语句可以设计空循环。 for(var i=0;i<10;i++) { ; } 上面代码可以简写为: for(var i=0;i<10;i++); 空语句易引发异常,安全的方法是使用复合语句的形式来表示,或者加上注释,避免遗漏。 for(var i=0;i<10;i++)/*空语句*/; //或者 for(var i=0;i<10;i++){ ; }
从结构上分
单句
单句一般由一个或多个关键字和表达式构成,用来完成运算、赋值等简单任务。
复句
复句一般由大括号构成,用来设计流程结构,控制程序的执行顺序。 复合语句末尾可以不用添加分号,但是句子之间必须使用分号分隔,大括号内最后一个句子可以省略分号,因为它不会产生歧义。
从功能上分
声明语句
var声明变量
声明一个或多个变量
function声明函数
可以声明一个函数
function f(){ alert("声明并初始化函数变量"); }
表达式语句
赋值语句
函数语句
变量声明语句
定义函数语句
选择语句
循环语句
主要有3种逻辑结构
顺序结构
一种线性、有序的结构,它依次执行各语句模块
循环结构
重复执行一个或几个模块,直到满足某一个条件为止。
while语句
do-while语句
do-while语句是while循环结构的特殊形式。
for语句
for-in
for-in语句是for语句的一种特殊形式
for([var] variable in<object | array>) statement
variable表示一个变量,可以在其前面符加var语句,用来直接声明变量名。in关键字后面是一个对象或数组类型的表达式。 在运行该循环结构时,会声明一个变量,然后计算对象或数组类型的表达式,并遍历该对象或表达式。在遍历过程中,每获取一个对象或数组元素,就会临时把对象或数组中元素存储在variable指定的变量中。注意,对于数组来说,该变量存储的是数组元素的下标;而对于对象来说,该变量存储的是对象的属性名或方法名。 然后,执行statement包含的语句。执行完毕,返回继续枚举下一个元素,以此周而复始,直到对象或数组中所有元素都被枚举为止。 在循环体内还可以通过中括号([])和临时变量variable来获取每个对象属性或数组元素的值。
语法格式
while(expression) statement //或 while(expression) statements
在while循环结构中,JavaScript会先计算expression表达式的值。如果循环条件返回值false,则会跳出循环结构,执行下面的语句;如果循环条件返回值为true,则执行循环体内的语句statement或循环体内的复合语句statements。 然后,再次返回计算expression表达式的值,并根据返回的布尔值决定是否继续执行循环体内语句。周而复始,直到expression表达式的值为false才会停止执行循环体内语句。
do statement while(expression); //或 do statements while(expression);
在do-while循环结构中,JavaScript会先执行循环体内语句statement或循环体内的复合语句statements,然后计算expression表达式的值。如果循环条件返回值为false,则会跳出循环结构,执行下面的语句;如果循环条件返回值为true,则再次返回执行循环体内的语句statement或循环体内的复合语句statements。 然后,再次计算expression表达式的值,并根据返回的布尔值决定是否继续执行循环体内语句。周而复始,直到expression表达式的值为false才会停止执行循环体内语句。
for(initialization;test;increment) statements
与while相比,for是优化的循环结构。 for循环结构把初始化变量、检测循环条件和递增变量都集中在for关键字后的小括号内,把它们作为循环结构的一部分固定下来,这样就可以防止在循环结构中忘记变量初始化,或者疏忽递增循环变量,同时也简化了操作。 在for循环结构开始执行之前,先计算第一个表达式initiialization,在这个表达式中可以声明变量,为变量赋值,或者通过逗号运算符执行其他操作。然后再执行第二个表达式test,如果该表达式的返回值为true,则执行循环体内的语句。最后返回计算increment表达式,这是一个具有副作用的表达式,与initialization表达式一样都可以赋值或改变变量的值,通常在该表达式中利用递增(++)或递减(--)运算符来改变循环变量的值。
选择结构
根据条件成立与否选择程序执行的通路。
if语句
if的多重选择结构执行效率比较低,特别是当选择条件相同时,由于重复调用if语句来计算条件表达式会浪费时间,此时建议使用switch语句设计多重选择结构。
switch语句
语法格式
if(expression) statement //或 if(expression) statements
if是关键字,表示条件命令;小括号作为运算符,用来分隔并计算条件表达式的值。expression表示条件表达式,statement表示单句,statements表示复句。 条件结构被执行时,先计算条件表达式的值,如果返回值为true,则执行下面的单句或复句;如果返回值为false,则跳出条件结构,执行结构后面的代码。如果条件表达式的值不为布尔值,则会强制转换为布尔值。
if语句加上else从句,可以设计二选一的程序结构,其语法格式如下 if(expression) <statement | statements> else <statement | statements>
switch(expression) { statements }
switch语句的statements比较特殊,它包含一个或多个case从句,或者包含一个default从句。完整结构如下。 switch(expression){ case label: statementList case label: statementList ... default: statementList }
当执行switch语句时,JavaScript解释器首先计算expression表达式的值,然后使用这个值与每个case从句中label标签表达式的值进行比较,如果相同则执行该标签下的语句。 在执行时如果遇到跳转语句,则会跳出switch结构。否则按顺序向下执行,直到switch语句末尾。如果没有匹配的标签,则会执行default从句下的语句。如果没有default从句,则跳出switch结构。 【示例】下列示例使用switch语句来设计多分支选择结构 switch(a=3){ //指定多重条件表达式 case 1: //从句1 alert(1); break; //停止执行,跳出switch结构 case 2: 从句2 alert(2); break; //停止执行,跳出switch结构 case 3: //从句3 }
else if语句
跳转结构
标签语句
label: statements
break语句
break;
break语句能够终止循环或多重选择结构的执行,只能用在循环结构和switch多重选择结构中
continue语句
continue与break一样都独立成句,但是break语句用于停止循环,而continue语句用于停止当前循环,继续执行下一次循环。 与break语句语法相同,continue语句可以跟随一个标签名,用来指定继续执行的循环结构的起始位置。
continue label;
return语句
异常处理结构
异常处理结构就是一套应对JavaScript代码发生错误时的处理方法,这套方法通过try/catch/finally结构语句来实现,把代码放在这个结构中执行就可以避免异常发生。
throw
throw语句能够主动抛出一个异常,告诉系统发生了异常状况或错误。
throw expression;
try-catch-finally
try-catch-finally语句是JavaScript异常处理器,其中try从句负责指明需要处理的代码块。catch从句负责捕获异常,并决定应对之策。finally从句负责后期处理工作,如清除代码、释放资源等。不管异常是否发生,finally从句最后都是要执行的。整个异常处理的结构和从句之间的相互关系如下。 try { //调试代码块 } catch(e) { //捕获异常并进行处理 } finally { //后期事务处理 } 在正常情况下,程序按顺序执行try从句中的代码。如果没有异常发生,将会忽略catch从句,跳转到finally从句中继续执行;如果在try从句中运行时发生错误或者使用throw语句主动抛出异常,则执行catch从句代码块,在该从句中通过参数变量引用抛出的Error对象或者其他值,同时定义处理异常的方法,或者忽略不计,或者再次抛出异常等。
第4章 使用数组
数组(Array)是合成类型的数据,属于引用型对象,不可作为简单的值来操作。数组是一组有序排列的数据集合,数组中每个值被称为元素,每个元素的索引位置被称为下标,下标值从0开始,有序递增。元素的值没有类型限制,数组的长度不固定,可以任意修改。
数组基础
定义数组的两种方法
构造数组
使用new运算符调用Array()函数时,可以创建一个新数组
数组直接量
指在中括号运算符中包含多个值列表,以逗号进行分隔
定义多维数组
JavaScript不支持多维数组,但是可以通过数组嵌套的形式定义多维数组。
读写数组
读写数组中元素的值可以通过中括号运算符([])来实现。中括号运算符左侧是数组标识符,中括号内包含数组元素的下标。
var a=[]; //声明一个空数组 a[0]=1; //为数组第1个元素赋值为1 a[1]=2; //为数组第2个元素赋值为2 alert(a[0]); //读取数组第1个元素的值,返回值为1 alert(a[1]); //读取数组第2个元素的值,返回值为2
数组长度
JavaScript为Array原型预定义length属性,length属性能够动态存储数组包含元素的个数
类数组
如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为“类似数组的对象”(Array-like Object),简称为类数组或伪类数组
检测数组
使用运算符in可以检测某个键名是否存在于数组中。注意,in运算符适用于对象,也适用于数组。
遍历数组
使用数组的forEach()方法、for-in语句结构以及Object.keys()方法都可以遍历数组元素。for-in循环不仅可以遍历对象,也可以遍历数组,毕竟数组只是一种特殊对象。
空位数组
当数组的某个下标位置是空元素,即两个逗号之间没有任何值,称该数组存在空位(Hole)
var a=[1,,1] a.length //3
代码显示,数组的空位不影响length属性。 如果最后一个元素后面有逗号,并不会产生空位。也就是说,有没有这个逗号,结果都一样。例如。 var a=[1,2,3,]; a.length //3 a //[1,2,3] 数组的空位是可以读取的,返回undefined var a=[,,,]; a[1] //undefined 使用delete运算符删除一个数组成员,会形成空位,但不会影响length属性。
使用Array
Array是JavaScript标准库对象,Array类型预定义了大量原型方法,所有数组对象都继承这些方法,灵活使用这些方法,可以解决很多实际问题。
判断数组
var a=[1,2,3]; typeof a //"object" Array.isArray(a) //true 从上面代码中,typeof运算符只能显示数组的类型是Object,而Array.isArray方法可以对数组返回true
增删数组
使用delete运算符只能删除数组元素的值,但是不能够删除元素;通过修改数组的length属性值,可以增删数组,但是使用不灵活
push()
//添加数组元素 var a=[]; a.push(1) //1 a.push('a') //2 a.push(true,{}) //4 a //返回[1,'a',true,{}]
//合并数组 var a=[1,2,3]; var b=[4,5,6]; Array.prototype.push.apply(a,b) 或者 a.push.apply(a,b) 上面两种写法等同于: a.push(4.5.6) a//[1,2,3,4,5,6]
pop()
//删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组 var a=['a','b','c']; a.pop(); //'c' a //['a','b'] 对空数组使用pop()方法,不会报错,而是返回undefined
push()和pop()方法结合使用,就构成“先进先出”的栈结构(Stack)。
shift()
用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组 var a=['a','b','c']; a.shift(); //'a' a //['b','c']
unshift()
//在数组的第一个 位置添加元素,并返回添加新元素后的数组长度。该方法会改变原数组 var a=['a','b','c']; a.unshift('x'); //4 a //['x','a','b','c']
合并数组
concat()
concat()方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。
['hello'].concat(['world']) //["hello","world"] ['hello'].concat(['world'],['!']) //["hello","world","!"]
转换为字符串
join()
var a=[1,2,3,4]; a.join('') //'1234' a.join('|') //"1|2|3|4" a.join() //"1,2,3,4"
join()方法能够以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔。
split()
使用字符串对象split()方法可以把字符串转换为数组,与join()方法操作正好相反。该方法可以指定两个参数,第一个参数为分隔符,指定从哪儿进行分隔的标记,第二个参数指定要返回数组的长度。
var s="1==2==3==4==5"; //定义字符串 s.split("=="); //返回数组[1,2,3,4,5]
toString()
var a=[1,2,3,4,5,6,7,8,9,0]; //定义数组 a.toString(); //返回字符串"1,2,3,4,5,6,7,8,9,0" var a=[[1,[2,3],[4,5]],[6,[7,[8,9],0]]]; //定义多维数组 a.toString(); //返回字符串"1,2,3,4,5,6,7,8,9,0"
toString()方法也能够返回数组的字符串形式,以逗号连接
toLocaleString()
var a[1,2,3,4,5]; //定义数组 a.toLocaleString(); //返回字符串"1.00,2.00,3.00,4.00,5.00"
toLocaleString()方法与toString()方法类似,主要区别在于toLocaleString()方法能够使用用户所在地区特定的分隔符把生产的字符串连接起来。 该代码中,toLocaleString()方法根据中国用户使用习惯,先把数字转换为浮点数之后再执行字符串转换操作。
valueOf()
var a=[1,2,3]; a.valueOf() //[1,2,3]
valueOf()方法能够返回数组本身。
截取数组
slice()
var a=['a','b','c']; a.slice(0) //["a","b","c"] a.slice(1) //["b","c"] a.slice(1,2) //["b"] a.slice(2,6) //["c"] a.slice() //["a","b","c"]
slice()方法用于提取原数组的一部分,返回一个新数组,原数组不变。 它的第一个参数为起始位置(从0开始),第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个元素。
var a=['a','b','c']; a.slice(4) //[] a.slice(2,1) //[]
如果参数值大于数组长度,或者第二个参数小于第一个参数,则返回空数组。
var a=['a','b','c']; a.slice(-2) //["b","c"] a.slice(-2,-1) //["b"]
如果slice()方法的参数是负数,则表示倒数计算的位置。
splice()
var a=['a','b','c','d','e','f']; a.spice(4,2) //["e","f"] a //["a","b","c","d"]
splice()方法用于删除原数组的一部分元素,并可以在被删除的位置添加新的数组元素,返回值是被删除的元素。注意,该方法会改变原数组。 splice()的第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多参数,则表示这些就是要被插入数组的新元素。
var a=['a','b','c','d','e','f']; a.splice(4,2,1,2) //["e","f"] a //["a","b","c","d",1,2]
该代码除了删除成员,还插入了两个新成员。
var a=[1,1,1]; a.splice(1,0,2) //[] a //[1,2,1,1]
如果只是单纯地插入元素,splice()方法的第二个参数可以设为0。
var a=[1,2,3,4]; a.spice(2) //[3,4] a //[1,2]
如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
排列数组
reverse()
var a=['a','b','c']; a.reverse() //["c","b","a"] a //["c","b","a"]
reverse()方法用于颠倒数组中元素的顺序,返回改变后的数组。注意,该方法将改变原数组。
sort()
['d','c','b','a'].sort() //['a','b','c','d'] [4,3,2,1].sort() //[1,2,3,4] [11.101].sort() //[101,11] [10111,1101,111].sort() //[10111,1101,111]
sort()方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。 上面代码的最后两个例子,需要特殊注意。sort()方法不是按照大小顺序,而是按照对应字符串的字典顺序排序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以101排在11的前面。
定位元素
indexOf()
var a=['a','b','c']; a.indexOf('b') //1 a.indexOf('y') //-1
indexOf()方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。
['a','b','c'].indexOf('a',1) //-1
indexOf()方法还可以接受第二个参数,表示搜搜的开始位置。
lastIndexOf()
var a[2,5,9,2]; a.lastIndexOf(2) //3 a.lastIndexOf(7) //-1
lastIndexOf()方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。
如果数组中包含NaN,这两种方法不适用,即无法确定数组成员是否包含NaN。 [NaN].indexOf(NaN) //-1 [NaN].lastIndexOf(NaN) //-1 这是因为这两种方法内部,使用严格相等运算符(===)进行比较,而NaN是唯一一个不等于自身的值。
迭代数组
map()
var numbers=[1,2,3]; numbers.map(function(n){ return n+1; }); //[2,3,4] numbers //[1,2,3]
map()方法对数组的所有元素依次调用一个函数,根据函数结果返回一个新数组。 在上面代码中,numbers数组的所有元素都加1,组成一个新数组返回,原数组没有变化。
forEach
forEach方法与map()方法很相似,也是遍历数组的所有成员,执行某种操作,但是forEach()方法一般不返回值,只用来操作数据。如果需要有返回值,一般使用map()方法。
function log(element,index,array){ console.log('['+index+']='+element); } [2,5,9].forEach(log); //[0]=2 //[1]=5 //[2]=9
forEach()方法的参数与map()方法一致,也是一个函数,数组的所有元素会依次执行该函数。它接受个参数,分别是当前位置的值、当前位置的编号和整个数组。 在上面代码中,forEach()遍历数组不是为了得到哦返回值,而是为了在屏幕输出内容,所以应该使用forEach()方法,而不是map()方法,虽然后者也可以实现同样目的。
过滤数组
filter()
[1,2,3,4,5].filter(function(elem){ return(elem>3); }) //[4,5]
使用filter()方法可以过滤数组。filter()方法的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。 该代码中将大于3的原数组成员,作为一个新数组返回。
验证数组
some()和every()方法用来判断数组元素是否符合某种条件。它们接受一个函数作为参数,所有数组元素依次执行该函数,返回一个布尔值。该函数接受3个参数,依次是当前位置的元素、当前位置的序号和整个数组。
some()
var arr=[1,2,3,4,5]; arr.some(function(elem,index,arr){ return elem>=3; }); //返回true
代码表示,如果存在大于等于3的数组元素,就返回true。
every()
var arr=[1,2,3,4,5]; arr.every(function(elem,index,arr){ return elem>=3; }); //返回false
every()方法则是所有元素的返回值都是true,才返回true,否则返回false。 代码中,只有所有数组元素大于等于3,才返回true。
function isEven(x){return x%2===0} [].some(isEven) //false [].every(isEven) //true
对于空数组,some()方法返回false,every()方法返回true,回调函数都不会执行。
汇总数组
reduce()
reduce()是从左到右处理(从第一个成员到最后一个成员)
[1,2,3,4,5].reduce(function(x,y){ console.log(x,y) return x+y; }) //1 2 //3 3 //6 4 //10 5 //最后结果:15
在上面代码中,第一轮执行,x是数组的第一个成员,y是数组的第二个成员。从第二轮开始,x为上一轮的返回值,y为当前数组成员,直到遍历完所有成员,返回最后一轮计算后的x。
reduceRight()
reduceRight()则是从右到左(从最后一个成员到第一个成员),其他完全一样。
这两种方法的第一个参数都是一个函数。该函数接受以下4个参数。 (1)累积变量,默认为数组的第一个成员。 (2)当前变量,默认为数组的第二个成员。 (3)当前位置(从0开始)。 (4)原数组。 这4个参数中,只有前两个是必需的,后两个则是可选的。
案例实战
交换变量值
设计交换两个变量的值,方法如下 var a=10,b=20; //变量初始化 var temp=a; //定义临时变量存储a a=b; //把b的值赋值给a b=temp; //把临时变量的值赋值给b 利用数组可以更灵巧,方法如下 a=[b,b=a][0];
使用关联数组
关联数组是一种具有特殊索引方式的数组,它的键名可以使用字符串或者其他类型的值(除null),或者是表达式,因此与键名关联的值没有固定的顺序。 在JavaScript中,对象本质就是一个关联数组,数组是对象的子类型。
为数组下标指定负值 var a=[]; //定义空数组 a[-1]=1; //下标为-1的元素赋值
扩展数组
初始化数组
数组去重
第5章 使用字符串
字符串就是零个或多个排在一起的字符,放在单引号或双引号之中。字符串处理在表单开发、HTML文本解析、异步响应等领域广泛使用,包括字符匹配、查找、替换、截取、编码/解码、连接等。
字符串基础
定义字符串
字符串直接量:使用双引号或单引号包含任意长度的字符文本。
'abc' "abc"
【示例1】如果字符串必须分行显示,可以在每一行的尾部使用反斜杠。 var longString="Long \ long \ long \ string"; 上面代码表示,加了反斜杠以后,原来写在一行的字符串,可以分成多行书写。但是,输出时还是单行,效果与写在同一行完全一样。注意,反斜杠的后面必须是换行符,而不能有其他字符(如空格),否则会报错。 【示例2】连接运算符(+)可以连接多个单行字符串,将长字符串拆成多行书写,输出时也是单行。 var longString='Long' +'long' +'long' +'string'; 【示例3】如果想输出多行字符串,有一种利用多行注释的变通方法。 (function(){/* line1 line2 line3 */}).toString().split('\n').slice(1,-1).join('\n')
构造字符串
使用String()构造函数可以构造字符串,该函数可以接收一个参数,并把它作为初始值来初始化字符串。
var s=new String(); //创建一个空字符串对象,并赋值给变量s var s=new String("我是构造字符串"); //创建字符串对象,初始化之后赋值给变量s
注意:通过String构造函数构造的字符串与字符串直接量的类型不同。前者为引用型对象,后者为值类型的字符串。 【示例5】下面代码比较了构造字符串和字符串直接量的数据类型不同。 var s1=new String(1); //构造字符串 var s2="1", //定义字符串直接量 alert(typeof s1); //返回object,说明是引用型对象 alert(typeof s2); //返回string,说明是值类型字符串 从上面示例可以看到,String构造函数实际上是字符串的包装类,利用它可以把值类型字符串包装为引用型对象,以实现特殊操作。 【示例6】String()也可以作为普通函数使用,把参数转换为字符串类型的值返回。 var s=String(123456); //包装字符串 alert(s); //返回字符串"123456" alert(typeof s); //返回string,说明该方法不再是构造函数 【示例7】String()可以带有多个参数,但是它仅处理第一个参数,并把它转换为字符串返回。 var s=String(1,2,3,4,5,6); //带有多个参数 alert(s); //返回字符串"1" alert(typeof s); //返回string,数值被转换为字符串
使用字符编码
fromCharCode()
字符串与数组
var s='hello'; s[0] //返回"h" s[1] //返回"e" s[4] //返回"o" //直接对字符串使用中括号运算符 'hello'[1] //"e"
字符串被视为字符数组,可以使用数组的中括号运算符来返回某个位置的字符(位置编号从0开始)。 【示例】如果中括号的数字超过字符串的长度,或者中括号中根本不是数字,则返回undefined。 'abc'[3] //返回undefined 'abc'[-1] //返回undefined 'abc'['x'] //返回undefined 【示例】字符串与数组只是相似,但是无法改变字符串中的单个字符。 var s='hello'; delete s[0]; s //"hello" s[1]='a'; s //"hello" s[5]='!'; s //"hello" 上面代码表示,字符串内部的单个字符无法改变和增删,这些操作会默默地失败。
字符串长度
length属性返回字符串的长度,该属性为只读,无法修改
var s='hello'; s.length //5 s.length=3; s.length //5 s.length=7; s.length //5
上面代码表示字符串的length属性无法改变,但是不会报错。 【拓展】获取字符串的长度,使用length属性在特定情况下是不精确的,因为字符包括单字节、双字节两种类型。
字符集
JavaScript使用Unicode字符集,允许在程序中直接使用Unicode编码表示字符,即将字符写成\uxxxx的形式,其中xxxx代表该字符的Unicode编码。例如 var s='\u00A9'; s //"©",\u00A9代表版权符号
Base64转码
Base64是一种编码方法,可以将任意字符转成可打印字符。使用这种编码方法,主要不是为了加密,而是为了不出现特殊字符,简化程序的处理
btoa()
字符串或二进制值转为Base64编码
atob()
Base64编码转为原来的编码
var string='Hello World!'; btoa(string) //"SGVsbG8gV29ybGQh" atob('SGVsbG8gV29ybGQh') //"Hello World!"
这两个方法不适合非ASCII码的字符,会报错。 要将非ASCII码字符转为Base64编码,必须中间插入一个转码环节,再使用这两个方法。
使用String
String是JavaScript标准库对象,预定义了很多原型方法,使用这些原型方法,可以方便用户灵活处理字符串。使用String()函数可以定义新字符串。
字符串的表示和值
toString()
使用toString()方法可以返回字符串的表示。
var s="javascript"; var a=s.toString(); //返回字符串"javascript" 由于该方法的返回值与字符串本身相同,所以一般不会调用这个方法
valueOf()
使用valueOf()方法可以返回字符串的值。
var s="javascript"; var a=s.valueOf(); //返回字符串"javascript"
连接字符串
把多个字符串连接在一起的最简单方法是使用加号运算符。
concat()
使用concat()方法也可以连接两个字符串,返回一个新字符串,不改变原字符串。 【示例】该方法可以接受多个参数。 'a'.concat('b','c') //"abc" 如果参数不是字符串,concat()方法会将其先转为字符串,然后再连接。 var one=1; var two=2; var three='3'; ".concat(one,two,three) //"123" one+two+three //"33" 在上面代码中,concat()方法将参数先转成字符串再连接,所以返回的是一个3个字符的字符串。作为对比,加号运算符在两个运算数都是数值时,不会转换类型,所以返回的是一个两个字符的字符串。
var s1='abc'; var s2='def'; s1.concat(s2) //"abcdef" s1 //"abc"
获取指定位置字符
charAt()
charAt()方法返回指定位置的字符,参数是从0开始编号的位置。 var s=new String('abc'); s.charAt(1) //"b" s.charAt(s.length-1) //"c" 这个方法完全可以用数组下标替代 'abc'.charAt(1) //"b" 'abc'[1] //"b" 如果参数为负数,或大于等于字符串的长度,charAt()返回空字符串。 'abc'.charAt(-1) //"" 'abc'.charAt(3) //""
charCodeAt()
charCodeAt()方法返回给定位置字符的Unicode编码(十进制表示),相当于String.from CharCode()的逆操作。 'abc'.charCodeAt(1) //98 上面代码中,abc的1号位置的字符是b,它的Unicode编码是98。 如果没有任何参数,charCodeAt()返回首字符的Unicode编码。 'abc'.charCodeAt() //97 上面代码中,首字符a的Unicode编号是97。 如果参数为负数,或大于等于字符串的长度,charCodeAt()返回NaN。 注意:charCodeAt()方法返回的Unicode编码不大于65536(0xFFFF),即只返回两个字节的字符的编码。如果遇到Unicode编码大于65536的字符,必需连续使用两次charCodeAt(),不仅读入charCodeAt(i),还要读入charCodeAt(i+1),将两个16字节放在一起,才能得到准确的字符。
获取字符的位置
indexOf()和laseIndexOf()方法用于确定一个字符串在另一个字符串中的位置,都返回一个整数,表示匹配开始的位置。如果返回-1,就表示不匹配。 二者的区别在于,indexOf()方法从字符串头部开始匹配,lastIndexOf()方法从尾部开始匹配。 例如: 'hello world'.indexOf('o') //4 'JavaScript'.indexOf('script') //-1 'hello world'.lastIndexOf('o') //7 它们还可以接受第二个参数,对于indexOf()方法,第二个参数表示从该位置开始向后匹配;对于lastIndexOf(),第二个参数表示从该位置起向前匹配。例如: 'hello world'.indexOf('o',6) //7 'hello world'.lastIndexOf('o',6) //4 提示:对于indexOf()方法的第二个参数: 如果值为负数,则视为0,就相当于从第一个字符开始查找。 如果省略了这个参数,也将从字符串的第一个字符开始查找。 如果值大于等于length属性值,则视为当前字符串中没有指定的子字符串,即返回-1。
indexOf()
lastIndexOf()
查找字符串
search()
search()方法查找参数字符串在调用字符串中第一次出现的位置。 var s="http://www.mysite.cn/index.html"; var n=s.search("//"); //返回值为5 提示: search()方法的参数为正则表达式(RegExp对象)。如果参数不是RegExp对象,则JavaScript会使用RegExp()构造函数把它转换成RegExp对象。 search()方法遵循从左到右的查找顺序,并返回第一个匹配的子字符串的起始下标位置。如果没有找到,则返回-1。 search()方法无法查找指定的范围,始终返回第一个匹配子字符串的下标位置。
match()
match()方法能够找出所有匹配的子字符串,并存储在一个数组中返回。例如: var s="http://www.mysite.cn/index.html"; var a=s.match(/h/g); //全局匹配所有字符h alert(a); //返回数组[h,h] 提示:match()方法返回的是一个数组,如果不是全局匹配,那么match()方法只能执行一次匹配。例如,下面匹配模式没有g修饰符,只能执行一次匹配,返回仅有一个元素h的数组。 var a=s.match(/h/); //返回数组[h] 如果没有找到匹配字符,则返回null,而不是空数组。 当不执行全局匹配时,如果匹配模式包含子表达式,则返回的数组中包含子表达式匹配的信息。
截取字符串
slice()
slice()方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。 'JavaScript'.slice(0,4) //"Java" 如果省略第二个参数,则表示子字符串一直到原字符串结束。 'JavaScript'.slice(4) //"Script" 如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。 'JavaScript'.slice(-6) //"Script" 'JavaScript'.slice(0,-6) //"Java" 'JavaScript'.slice(-2,-1) //"p" 如果第一个参数大于第二个参数,slice()方法返回一个空字符串。 'JavaScript'.slice(2,1) //""
substring()
substring()方法用于从原字符串取出子字符串并返回,不改变原字符串。它与slice()作用相同,但有一些奇怪的规则,因此不建议使用这个方法,优先使用slice()。 substring()方法的第一个参数表示子字符串的开始位置,第二个位置表示结束位置。例如: 'JavaScript'.substring(0,4) //"Java" 如果省略第二个参数,则表示子字符串一直到原字符串结束。 'JavaScript'.substring(4) //"Script" 如果第二个参数大于第一个参数,substring()方法会自动更换两个参数的位置。 'JavaScript'.substring(10,4) //"Script" //等同于 'JavaScript'.substring(4,10) //"script" 在上面代码中,调换substring()方法的两个参数,得到同样的结果。 如果参数是负数,substring()方法会自动将负数转为0。 'Javascript'.substring(-3) //"JavaScript" 'JavaScript'.substring(4,-3) //"Java" 上面第二行代码,参数-3会自动变成0,等同于'JavaScript'.substring(4,0)。由于第二个参数小于第一个参数,会自动互换位置,所以返回Java。
substr()
substr()方法用于从原字符串取出子字符串并返回,不改变原字符串。 substr()方法的第一个参数是子字符串的开始位置,第二个参数是子字符串的长度。例如: 'JavaScript'.substr(4,6) //"Script" 如果省略第二个参数,则表示子字符串一直到原字符串结束。 'JavaScript'.substr(4) //"Script" 如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串。 'JavaScript'.substr(-6) //"Script" 'JavaScript'.substr(4,-1) //"" 上面第二行代码,由于参数-1自动转为0,表示子字符串长度为0,所以返回空字符串。
替换字符串
replace()
replace()方法能够实现字符串替换,该方法包含两个参数,第一个参数表示执行匹配的正则表达式,第二个参数表示准备代替匹配的子字符串。 【示例】下面代码使用replace()方法修改字符串中html为htm。 var s="http://www.mysite.cn/index.html"; var b=s.replace(/html/,"htm"); //把字符串html替换为htm alert(b); //返回字符串"http://www.mysite.cn/index.htm" 该方法第一个参数是一个正则表达式对象,也可以传递字符串。如下。 var b=s.replace("html","htm"); //把字符串html替换为htm
【示例】在replace()方法中约定了一个特殊的字符($),这个美元符号如果附加一个序号就表示对正则表达式中匹配的子表达式存储的字符串引用。 var s="javaascript"; var b=s.replace(/(java)(script)/,"$2-$1"); //交换位置 alert(b); //返回字符串"script-java"
在上面示例中,正则表达式/(java)(script)/中包含两对小括号,按顺序排列,其中第一对小括号表示第1个子表达式,第二对小括号表示第2个字表的是,在replace()方法的参数中可以分别使用字符串"$1"和"$2"来表示对它们匹配文本的引用,当然它们不是标识符,仅是一个标记,所以不可以作为变量参与计算。除了上面约定之后,美元符号与其他特殊字符组合还可以包含更多的语义,详细说明如表。
【示例】重复字符串 var s="javascript"; var b=s.replace(/.*/,"$&$&"); //返回字符串"javascriptjavascript" 由于字符串"$&"在replace()方法中被约定为正则表达式所匹配的文本,所以利用它可以重复引用匹配的文本,从而实现字符串重复显示效果。其中正则表达式”/.*“表示完全匹配字符串。
大小写转换
【示例】下面代码把字符串全部转换为大写形式 var s="javascript"; alert(s.toUpperCase()); //返回字符串”JAVASCRIPT“ String类型定义了toLocaleLowerCase()和toLocaleUpperCase()两个本地化方法。它们能够按照本地方式转换大小写字母,由于只有几种语言(如土耳其语)具有地方特有的大小写映射,所以通常与toLowerCase()和toUpperCase()方法的返回值一样。
比较字符串
JavaScript在比较字符串大小时,根据字符的Unicode编码大小,逐位进行比较。 例如,小写字母a的编码为97,大写字母A的编码为65,则比较时字符串"a"就大于"A"。 alert("a">"A"); //返回true
转换为数组
使用split()方法可以根据指定的分隔符把字符串分解为数组,数组中不包含分隔符。 【示例】如果参数为空字符串,则split()方法能够按单子字符进行分切,然后返回与字符串等长的数组。 var s="javascript"; var a =s.split(""); //按字符空隙分割 alert(s.length); //返回值为10 alert(a.length); //返回值为10 【示例】如果参数为空,则split()方法能够把整个字符串作为一个元素的数组返回,它相当于把字符串转换为数组。 var s="javascript"; var a=s.split(); //空分割 alert(a.constructor==Array); //返回true,说明是Array实例 alert(a.length); //返回值为1,说明没有对字符串进行分割 【示例】如果参数为正则表达式,则split()方法能够以匹配文本作为分隔符进行切分。 var s="a2b3c4d5e678f12g"; var a=s.split(/\d+/); //把匹配的数字作为分隔符来切分字符串 alert(a); //返回数组[a,b,c,d,e,f,g] alert(a.length); //返回数组长度为7 【示例】如果正则表达式匹配的文本位于字符串的边沿,则split()方法也执行分切操作,且为数组添加一个空元素。但是在IE浏览器中会忽略边沿空的字符串,而不是把它作为一个空元素来看待。 var s="122a2b3c4d5e678f12g"; //虽然字符串左侧也有匹配的数字 var a=s.split(/\d+/); //把匹配的数字作为 分隔符来切分字符串 alert(a); //返回数组[,a,b,c,d,e,f,g] alert(a.length); //返回数组长度为8 如果在字符串中指定的分隔符没有找到,则返回一个包含整个字符串的数组。 【示例5】split() 方法支持第二个参数,该参数是一个可选的整数,用来指定返回数组的最大长度。如果设置了该参数,则返回的数组长度不会大于这个参数指定的值;如果没有设置该参数,那么整个字符串都被分割,不会考虑数组长度。 var s = "JavaScript"; var a = s.split("", 4); //按顺序从左到右,仅分切4个元素的数组 console.log(a); //返回数组[J,a,v,a] console.log(a.length); //返回值为4 【示例6】如果想使返回的数组包括分隔符或分隔符的一个或多个部分,可以使用带子表达式的正则表达式来实现。 var s = "aa2bb3cc4dd5e678f12g"; var a = s.split(/(\d)/); //使用小括号包含数字分隔符 console.log(a); //返回数组[aa,2,bb,3,cc,4,dd,5,e,6,,7,,8,f,1,,2,g]
修剪字符串
trim方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。 例如: ' hello world '.trim() //"hello world" 该方法去除的不仅是空格,还包括制表符(\t、\v)、换行符(\n)和回车符(\r)。 '\r\nabc \t'.trim() //'abc' 【拓展】也可以自定义修剪方法,以实现更灵活的操作字符串。
案例实战
格式化字符串
这些方法没有获得ECMAScript标准的支持,应谨慎使用。 【例】下面演示了如何使用上面字符串方法为字符串定义格式化显示属性。 var s="abcdef"; document.write(s.bold()); //定义加粗显示字符串"abcdef" document.write(s.link("http://www.mysite.cn/")); //为字符串"abcdef"定义超链接,指向mysite.cn域名 document.write(s.italics()); //定义斜体显示字符串"abcdef" document.write(s.fontcolor("red")); //定义字符串"abcdef"红色显示
anchor()
返回HTML a标签中name属性值为String字符串文本的锚
big()
返回HTML big标签定义的大字体
blink()
返回使用HTML blink标签定义的闪烁字符串
bold()
返回使用HTML b标签定义的粗体字符串
fixed()
返回使用HTML tt标签定义的单间距字符串
fontcolor()
返回使用HTML font标签中color属性定义的带有颜色的字符串
fontsize()
返回使用HTML font标签中size属性定义的指定尺寸的字符串
italics()
返回使用HTML i标签定义的斜体字符串
link()
返回使用HTML a标签定义的链接
small()
返回使用HTML small标签定义的小字体的字符串
strike()
返回使用HTML strike标签定义删除线样式的字符串
sub()
返回使用HTML sub标签定义的下标字符串
sup()
返回使用HTML sup标签定义的上标字符串
字符编码和解码
网页URL的合法字符分成两类。 URL元字符:分号(;)、逗号(’,‘)、斜杠(/)、问号(?)、冒号(:)、at(@)、&、等号(=)、加号(+)、美元符号($)、井号(#)。 语义字符:a-z、A-Z、0-9、连词符(-)、下划线(_)、点(.)、感叹号(!)、波浪线(~)、星号(*)、单引号(')、圆括号(()`)。 除了以上字符,其他字符出现在URL之中都必须转义,规则是根据操作系统的默认编码,将每个字节转为百分号(%)加上两个大写的十六进制字母。例如,UTF-8的操作系统上,"http://www.example.com/q=春节"这个URL中,汉字“春节”不是URL的合法字符,所以被浏览器自动转成"http://www.example.com/q=%E6%98%A5%E8%8A%82"。其中,“春”转成%E6%98%A5,“节”转成“%E8%8A%82”。这是因为“春”和“节”的UTF-8编码分别是E6 98 A5和E8 8A 82,将每个字节前面加上百分号,就构成URL编码。 JavaScript提供4个URL的编码/解码方法:encodeURI()、encodeURIComponent()、decodeURI()和decodeURIComponent(),具体说明如下。
escape()
escape()是不完全编码的方法,它仅能将字符串中某些字符替换为十六进制的转义序列。具体说,就是除了ASCII字母、数字和标点符号(如@、*、_、+、-、.和')之外,所有字符都被转换为%xx或%uxxxx(x表示十六进制的数字)的转义序列。从\u0000到\u00ff的Unicode字符由转义序列%xx替代,其他所有Unicode字符由%uxxxx序列替代。
使用转义序列替换某些字符来对字符串进行编码
unescape()
对使用escape()编码的字符串进行解码
encodeURI()
通过转义某些字符对URI进行编码
decodeURI()
对使用encodeURI()方法编码的字符串进行解码
encodeURIComponent()
通过转义某些字符对URI的组件进行编码
decodeURIComponent()
对使用encodeURIComponent()方法编码的字符串进行解码
Unicode编码和解码
所谓Unicode编码就是根据字符在Unicode字符表中的编号对字符进行简单的编码,从而实现对信息进行加密。例如,字符“中”的Unicode编码为20013,如果在网页中使用Unicode编码显示,则可以输入“中”。因此,把文本转换为Unicode编码之后在网页中显示,能够实现加密信息的效果。
字符串智能转换
过滤敏感词
特殊字符检测和过滤是字符串操作中的常见任务。可以为String类型拓展一个方法check(),用来检测字符串中是否包含指定的特殊字符。 设计思路:方法check()的参数为任意长度和个数的特殊字符列表,检测的返回结果为布尔值。如果检测到任意指定的特殊字符,则返回true,否则返回false。
第6章 使用正则表达式(Refular Expression)
正则表达式是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用作按照“给定模式”匹配文本的工具。如正则表达式给出一个Email地址的模式,然后用它来确定一个字符串是否为Email地址。JavaScript的正则表达式体系是参照Perl5建立的。
新建正则表达式
方法一:使用直接量
/pattern/attributes
正则表达式直接量使用斜杠作为分隔符进行定义,两个斜杠之间包含的字符为正则表达式的字符模式,字符模式不能使用引号,修饰字符放在最后一个斜杠的后面。
方法二:使用RegExp()构造函数
new RegExp(pattern,attributes)
参数pattern可以是一个字符串,指定正则表达式的匹配模式,也可以是一个正则表达式;参数attributes是一个可选的修饰符,包含"g"、"i"和"m",分别用于指定全局匹配、区分大小写的匹配和多行匹配。如果pattern是正则表达式,而不是字符串,则必须省略该参数。 该函数将返回一个新的RegExp对象,具有指定的模式和修饰符。
匹配规则基础
字面量字符
大部分字符在正则表达式中,就是字面的含义。例如,/a/匹配a,/b/匹配b。
元字符
除了字面量字符以外,还有一部分字符有特殊含义,不代表字母的意思,叫做“元字符”,主要有以下几个
点字符
点字符(.)匹配除回车(\r)、换行(\n)、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符。
/c.t/
在上面代码中,c.t匹配c和t之间包含任意一个字符的情况,只要这3个字符在同一行,如cat、c2t、c-t等,但是不匹配coot。
位置符
^:表示字符串的开始位置
$:表示字符串的结束位置
选择符
竖线符号(|)在正则表达式中表示“或”(OR),如cat|dog表示匹配cat或dog。
/11|22/.test('911') //true
在上面代码中,正则表达式指定必须匹配11或22。 【例】多个选择符可以联合使用。 //匹配fred、barney、betty中的一个 /fred|barney|betty/
转义字符
在正则表达式中,那些有特殊含义的字符,如果要匹配它们本身,就需要在它们前面加上反斜杠。 【例】如要匹配加号,就要写成\+。 /1+1/.test('1+1') //false /1\+1/.test('1+1') //true 在上面代码中,第一个正则表达式直接用加号匹配,结果加号解释成量词,导致不匹配。第二个正则表达式使用反斜杠对加号转义,就能匹配成功。 提示:在正则匹配模式中,需要用斜杠转义的,一共有12个字符:^、.、[、$、(、)、|、*、+、?、{和\\。 注意:如果使用RegExp()构造函数生成正则表达式对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。例如: (new RegExp('1+1')).test('1+1') //false (new RegExp('1\\+1')).test('1+1') //true 在上面代码中,RegExp()作为构造函数,参数是一个字符串。但是,在字符串内部,反斜杠也是转义字符,所以它会先被反斜杠转义一次,然后再被正则表达式转义一次,因此需要两个反斜杠转义。
特殊字符
正则表达式对一些不能打印的特殊字符,提供了表达方法。
\cX
表示Ctrl-[X],其中的X是A-Z中任一个英文字母,用来匹配控制字符。
[\b]
匹配退格键(U+0008),不要与\b混淆。
\n
匹配换行键
\r
匹配回车键
\t
匹配制表符tab(U+0009)
\v
匹配垂直制表符(U+000B)
\f
匹配换页符(U+000C)
\0
匹配null字符(U+0000)
\xhh
匹配一个以两位十六进制数(\x00-\xFF)表示的字符
\uhhhh
匹配一个以四位十六进制数(\u0000-\uFFFF)表示的unicode字符。
字符类(Class)
字符类表示有系列字符可供选择,只要匹配其中一个即可。所有可供选择的字符都放在方括号内,如[xyz]表示x、y、z之中任选一个匹配。 /[abc]/.test('hello world') //false /[abc]/.test('apple') //true 上面代码表示,字符串'hello world'不包含a、b、c这3个字母中的 任一个,而字符串'apple'包含字母a。
字符类表示有系列字符可供选择,只要匹配其中一个即可。
脱字符
如果方括号内的第一个字符是脱字符[^],则表示除了字符类之中的字符,其他字符都可以匹配。如[^xyz]表示除了x、y、z之外都可以匹配。 /[^abc]/.test('hello world') //true /[^abc]/.test('bbc') //false 上面代码表示,字符串'hello world'不包含字母a、b、c中的任一个,所以返回true;字符串'abc'不包含a、b、c以外的字母,所以返回false。 如果方括号内没有其他字符,只有[^],就表示匹配一切字符,其中包括换行符,而点号(.)不包括换行符。
连字符
某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。如[abc]可以写成[a-c],同理[A-Z]表示26个大写字母 /a-z/.test('b') //false /[a-z]/.test('b') //true 在上面代码中,当连字号(dash)不出现在方括号之中,就不具备简写的作用,只代表字面的含义,所以不匹配字符b。只有当连字号用在方括号之中,才表示连续的字符序列
预定义模式
指的是某些常见模式的简写方式。
\d
匹配0-9的任一数字,相当于[0-9]
\D
匹配所有0~9以外的字符,相当于[^0-9]
\w
匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
\W
除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
\s
匹配空格(包括制表符、空格符、断行符),相等于[\t\r\n\v\f]
\S
匹配非空格的字符,相当于[^\t\r\n\v\f]
\b
匹配词的边界
\B
匹配非词边界,即在词的内部
重复类
模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。 /lo{2}k/.test('look') //true /lo{2,5}k/.test('looook') //true 上面代码中,第一个模式指定o连续出现两次,第二个模式指定o连续出现2~5次。
量词字符
量词用来设定某个模式出现的次数,具体说明如下。 //t出现0次或1次 /t?est/.test('test') //true /t?est/.test('est') //true //t出现1次或多次 /t+est/.test('test') //true /t+est/.test('ttest') //true /t+est/.test('est') //false //t出现0次或多次 /t*est/.test('test') //true //.test('ttest') //true /t*est/.test('tttest') //true /t*est/.test('est') //true
?
问号,表示某个模式出现0次或1次,等同于{0,1}。
*
星号,表示某个模式出现0次或多次,等同于{0,}。
+
加号,表示某个模式出现1次或多次,等同于{1,}。
贪婪模式
上述3个量词字符,在默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止,这被称为贪婪模式。 var s='aaa'; s.match(/a+/) //["aaa"] 上面代码中,模式是/a+/,表示匹配1个a或多个a,那么到底会匹配几个a呢?因为默认是贪婪模式,会一直匹配到字符a不出现为止,所以匹配结果是3个a。 如果想将贪婪模式改为非贪婪的模式,可以在量词符后面加一个问号。 var s='aaa'; s.match(/a+?/) //["a"]
/字符+/
非贪婪模式
/字符+?/
表示某个模式出现0次或多次,匹配时采用非贪婪模式
/字符*?/
表示某个模式出现1次或多次,匹配时采用非贪婪模式
修饰字符(modifier)
修饰字符表示模式的附加规则,放在正则匹配模式的最尾部。修饰符可以单个使用,也可以多个一起使用。例如 //单个修饰符 var regex=/test/i; //多个修饰符 var regex=/test/ig;
g修饰符
在默认情况下,第一次匹配成功后,正则表达式对象就停止了向下匹配。g修饰符表示全局匹配(Global),加上它以后,正则表达式对象将匹配全部符合条件的结果,主要用于搜索和替换。
i修饰符
在默认情况下,正则表达式对象区分字母的大小写,加上i修饰符以后表示忽略大小写(ignorecase)。例 /abc/.test('ABC') //false /abc/i.test('ABC') //true 上面代码表示,加了i修饰符以后,不考虑大小写,所以模式abc匹配字符串ABC。
m修饰符
m修饰符表示多行模式(Multiline),会修改^和$的行为。默认情况下(即不加m修饰符时),^和$匹配字符串的 开始处和结尾处,加上m修饰符以后,^和$还会匹配行首和行尾,即^和$会识别换行符(\n)。 /world$/.test('hello world\n') //false /world$/m.test('hello world\n') //true 上面的代码中,字符串结尾处有一个换行符。如果不加m修饰符,匹配不成功,因为字符串的结尾不是world;加上以后,$可以匹配行尾。 /^b/m.test('a\nb') //true 上面代码要求匹配行首的b,如果不加m修饰符,就相当于b只能处在字符串的开始处。
模式分组
使用小括号可以对正则表达式字符串进行任意分组,在小括号内的字符串表示子表达式,或者称为子模式,子表达式具有独立的匹配功能,匹配结果也具有独立性。同时跟随在小括号后的量词将会作用于整个子表达式。 在正则表达式中,表达式分组具有极高的应用价值,
非引用组
正则表达式分组会占用一定的系统资源,在较长的正则表达式中,存储反向引用会降低匹配速度。但是很多时候使用分组仅是为了设置操作单元,而不是为了引用,这时建议选用一种非引用型分组,它不会创建反向应用。 创建非引用型分组的方法是,在左括号的后面分别加上一个问号和冒号(?:),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。
声明边界
正向声明
声明表示条件的意思,是指定匹配模式后面的字符必须被匹配,但不返回匹配结果。正向声明使用“(?=匹配条件)”表示。
反向声明
与正向声明匹配相反,指定接下来的字符都不必匹配。反向声明使用“(?!匹配条件)”来表示。
使用RegExp
RegExp是JavaScript标准库对象,JavaScript通过内置RegExp类型支持正则表达式,String和RegExp类型都提供了执行正则表达式匹配操作的方法。
RegExp对象属性
一类是修饰符相关,返回一个布尔值,表示对应的修饰符是否设置
var r=/abc/igm; r.ignoreCase //true r.global //true r.multiline //true
ignoreCase
返回一个布尔值,表示是否设置了i修饰符,该属性只读。
global
返回一个布尔值,表示是否设置了g修饰符,该属性只读
multiline
返回一个布尔值,表示是否设置了m修饰符,该属性只读
另一类是与修饰符无关的属性,主要有两个
var r=/abc/igm; r.lastIndex //0 r.source //"abc"
lastIndex
返回下一次开始搜索的位置。该属性可读写,但是只在设置了g修饰符时有意义。
source
返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
test()
正则表达式对象的test()方法返回一个布尔值,表示当前模式是否能匹配参数字符串。 /cat/.test('cats and dogs') //true 上面代码验证参数字符串中是否包含cat,结果返回true
exec()
正则表达式对象的exec()方法,可以返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回null。 exec()方法的返回数组还包含以下两个属性
input:整个原字符串
index:整个模式匹配成功的开始位置(从0开始计数)
RegExp静态属性
RegExp类型定义一组静态属性,访问它们可以了解当前页面最新一次模式匹配的详细信息,具体说明如下。这些静态属性都有两个名字:长名(全称)和短名(简称,以美元符号开头表示) RegExp 静态属性 长名 短名 说明 input $_ 返回当前所作用的字符串,初始值为空字符串"" index 当前模式匹配的开始位置,从 0 开始计数。初始值为 -1,每次成功匹配时,index 属性值都会随之改变 lastIndex 当前模式匹配的最后一个字符的下一个字符位置,从 0 开始计数,常被作为继续匹配的起始位置。初始值为 -1,表示从起始位置开始搜索,每次成功匹配时,lastIndex 属性值都会随之改变 lastMatch $& 最后模式匹配的字符串,初始值为空字符串""。在每次成功匹配时,lastMatch 属性值都会随之改变 lastParen $+ 最后子模式匹配的字符串,如果匹配模式中包含有子模式(包含小括号的子表达式),在最后模式匹配中,最后一个子模式所匹配到的子字符串。初始值为空字符串""。在每次成功匹配时,lastParen属性值都会随之改变 leftContext $` 在当前所作用的字符串中,最后模式匹配的字符串左边的所有内容。初始值为空字符串""。每次匹配成功时,其属性值都会随之改变 rightContext $' 在当前所作用的字符串中,最后模式匹配的字符串右边的所有内容。初始值为空字符串""。每次匹配成功时,其属性值都会随之改变 $1~$9 $1~$9 只读属性,如果匹配模式中有小括号包含的子字符串,$1~$9 属性值分别是第 1 个到第 9 个子模式所匹配到的内容。如果有超过 9 个以上的子模式,$1~$9 属性分别对应最后的 9 个子模式匹配结果。在一个匹配模式中,可以指定任意多个小括号包含的子模式,但 RegExp 静态属性只能存储最后 9 个子模式匹配的结果。在 RegExp 实例对象的一些方法所返回的结果数组中,可以获得所有圆括号内的子匹配结果
案例实战
匹配十六进制颜色值
匹配时间
匹配日期
匹配成对标签
货币数字的千位分隔符表示
验证密码
第7章 使用函数
函数对任何一门语言来说都是核心的概念,通过函数可以封装多条语句,可以在任何地方、任何时候调用执行。在JavaScript语言中,函数即对象,程序可以随意操控它们。函数可以嵌套在其他函数中定义,这样就可以访问它们被定义时所处的作用域中的任何变量,函数给JavaScript带来了非常强劲的编程能力。
函数基础
声明函数
function funName([args]){ statements }
funName是函数名,与变量名一样都是JavaScript合法的标识符,必须遵循JavaScript标识符命名约定。在函数名之后是一个由小括号包含的参数列表,参数之间以逗号分隔,函数的参数是可选的。这些参数将作为函数体内的变量标识符被访问。调用函数时,用户可以通过函数参数来干预函数内部代码的运行。 在小括号之后是一个大括号分隔符,大括号内包含的语句就是函数体结构的主要内容。在函数体结构中,大括号必不可少,缺少了这个大括号,JavaScript将会抛出语法错误。 【例】function语句必须包含函数名称、小括号和大括号,其他的都可省略,因此最简单的函数体是一个空函数。 function f(){ //空函数 } 下面代码命名了一个print函数,以后使用print()这种形式,即可调用相应的代码。 function print(s){ console.log(s); } 省略函数名,可以定义匿名函数,匿名 函数一般参与表达式运算,很少单独存在。 function //匿名空函数 }
定义函数表达式
构造函数
Function
定义嵌套函数
函数可以相互嵌套,因此可以定义复杂的嵌套结构函数
函数的返回值
在函数体内,使用return语句可以设置函数的返回值,一旦执行return语句,它将停止函数的运行,并把return关键字后面的表达式的运算之返回。如果函数不包含return语句,则执行完函数体内每条语句后,最后返回undefined值。
调用函数
函数在默认状态下不会被执行,一般使用小括号运算符(())来激活函数运行,在小括号运算符中可以包含零个或多个参数,参数之间通过逗号进行分隔。参数也可以是表达式,通过运算产生一个参数值。 每个参数值被赋予函数声明时定义的形参。当实际参数(arguments)的个数与形式参数(parameters)的个数不匹配时不会导致运行时错误。如果实际参数值过多,超出的参数值将被忽略。如果实际参数值过少,缺失的值将被替换为undefined。不会对参数值进行类型检查,任何类型的值都可以被传递给参数。
函数作用域
JavaScript把函数视为一个封闭的结构体,与外界完全独立,在函数内声明的变量、参数、私有函数等对外是不可见的。
函数的标识符
其中this和arguments是系统默认标识符,不需要特别声明。这些标识符在函数体内的优先级是(其中左侧优先级要大于右侧): this→局部变量→形参→arguments→函数名
函数参数
arguments
局部变量
内部函数
this
使用arguments
由于JavaScript允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数,这就是arguments对象的由来。 arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部才可以使用。
认识arguments对象
arguments对象表示参数集合,它是一个类数组,拥有与数组相似的结构,可以通过数组下标的形式访问函数实参值,但是没有基础Array的原型方法。
使用callee
应用arguments
使用Function
Function是JavaScript内置构造对象,函数作为对象来使用,也可以构造其他对象。同时Function定义了多个原型方法,方便函数调用,以实现灵活的函数式编程
name属性
name属性返回紧跟在function关键字之后的函数名。
length属性
length属性返回函数预期传入的参数个数,即函数定义时的形参个数,为只读属性。
toString()
返回函数的源码
call()和apply()
具有两种应用场景
全局模式
将"use strict"放在脚本文件第一行,则整个脚本都将以严格模式运行。如果这行语句不在第一行,则无效,整个脚本将以正常模式运行。严格地说,只要前面不是产生实际运行结果的语句,"use strict"可以不在第一行
<script> "use strict"; console.log("这是严格模式。"); </script> <script> console.log("这是正常模式。"); </script>
局部模式
将"use strict"放到函数内的第一行,则整个函数将以严格模式运行
function strict(){ "use strict"; return"这是严格模式。"; } function notStrict(){ return"这是正常模式。"; }
模块模式
因为全局模式不利于文件合并,所以更好的做法是,借用局部模式的方法,将整个脚本文件放在一个立即执行的匿名函数中
(function(){ "use strict"; //在这里编写JavaScript代码 })()
启用
在代码首部加入如下注释字符串即可 “use strict”
目的
消除JavaScript语法的一些不合理、不严谨之处,减少一些怪异行为
消除代码运行的一些不安全之处,保证代码运行的安全
提高编译器效率,增加运行速度
为未来新版本的JavaScript做好铺垫
分号
分号是JavaScript语句分隔符,用来分隔不同的语句。 【示例1】下面代码虽在同一行内显示,但通过分号被分为3个语句。 var a = 1; var b = 2; var c = 3; 由于JavaScript默认独立一行的代码为一个语句,所以可以省略分号,但是如果把多句代码写在一行内显示,则必须增加分号。 【示例2】对于上面代码可以按如下方式进行书写: var a = 1; var b = 2; var c = 3; 或者: var a = 1 var b = 2 var c = 3 考虑到JavaScript程序可能会被压缩为一行显示,为了避免错误,建议大家养成好的习惯,不管一行内语句是否完整,只要是完整的语句都必须增加分号以表示句子的结束。 注意,在程序结尾或大括号}之前的分号也可以省略。 在长句中可以分行显示,以方便阅读。在分行时应确保一行内不能形成完整的逻辑语义,避免JavaScript解析器自动增加分号。 【示例3】下面代码是一个连续赋值的语句,通过分行显示可以更清楚地查看它们的关系。这种分行显示,由于一行内不能形成独立的逻辑语义,所以JavaScript解析器不会把每一行视为独立的句子,从而不会产生歧义。 var a = b = c = 4; // 分行显示的一个句子 如果在一行内显示则如下所示: var a = b = c = 4; // 单行显示的一个句子 【示例4】下面这个语句定义一个变量i,然后为其赋值,如果变量a为true,则赋值为1,否则就判断变量b,如果为true,则赋值为2,否则就判断变量c,如果为true,则赋值为3,否则赋值为4。 var i = a ? 1 : b ? 2 : c ? 3 : 4; 下面的分行显示就是错误的,因为表达式a ? 1: b能够形成独立的逻辑语义,所以JavaScript解析器会自动在其后添加分号来表示一个独立的句子。 var i = a ? 1: b ? 2 : c ? 3 : 4; // 错误的分行显示 安全的方法应该按如下所示分行显示。这样每一行都不能形成独立的语义。 var i = a ? 1 : b ? 2 : c ? 3 : 4; // 安全的分行显示 【提示】 JavaScript并不是在所有换行处都自动填补分号,只有在缺少了分号就无法正确解析代码的时候,JavaScript才会填补分号。因此,如果当前语句和随后的非空格字符不能当成一个整体来解析的话,JavaScript就在当前语句行结束处填补分号。 例如,如果第一行语句以 (、[、/、+或-结束,那么它极有可能和第二行语句合在一起解析。类似的还有return、break和continue语句。 也有例外:在涉及++和--运算符的时候,这些运算符可以作为表达式的前级,也可以当做表达式的后缀。如果将其用做后缀表达式,它和表达式应当在同一行。否则,行尾将自动填补分号,同时++和--将会作为下一行代码的前级操作符并与之一起解析。例如: x ++ y 将被解析为x;++y;,而不是x++;y;。
基本语法是一系列强制性或约束性的规定。首先有4点。 (1)编写代码时要区分大小写; (2)对于空格等分隔符,JavaScript引擎不会解析,可以忽略,因此可以使用分隔符格式化代码。 (3)要正确使用“//注释信息”或“/*注释信息*/”语法注释代码。 (4)了解标识符号命名基本约定,了解关键字、保留字、转义字符等概念。