本章内容:语法、数据类型、流控制语句、函数。
1.语法
ECMAScrip的语法和C和其他类C语言(如JAVA和Perl)的语法大同小异。
2.区分大小写
ECMAScript中的一切(变量、函数名和操作符)都区分大小写。
3.标识符
指变量、函数、属性的名字,或者函数的参数。也可以是按照下列格式规则组合起来的一或多个字符:
(1) 第一个必须是一个字母、下划线(_)或一个美元符号($);
(2) 其他字符可以字母、下划线、美元符号或数字。
(3) 扩展的ASCII或Unicode字母字符,但是不推荐这样做。
注:ECMAScript标识符采用驼峰大小写格式
不能把关键字、保留字、true、false和null用作标识符
4.注释
ECMAScript包括单行注释和块级注释。
单行注释以两个斜杠开头,如下所示:
//单行注释
块级注释以一个斜杠和一个星号(/*)开头,以一个星号和一个斜杠(*/)结尾。如下所示:
/* *这是一个多行 *(块级)注释 */
第二三行以星号开头并不是必需的。之所以添加,提高注释的可读性
5.严格模式
ECMAScript引入了严格模式的概念。是为JavaScript定义了一种不同的解析与执行模型。在严格模式下,ECMAScript中的一些不确定的行为将得到处理,而且对某些不安的操作抛出错误。
在函数内部的上方包含这条编译提示,也可以指定函数在严格模式下执行:
function doSomething() { "use strict"; //函数体 }
这行代码看起来像是字符串,而且也没有赋值给任何变量,但其实它是一个编译指示,用于告诉支持的JavaScript引擎切换到严格模式。
严格模式下,JavaScript的执行结果会有很大不同。支持严格模式的浏览器包括IE10+、Firefox4+、Safari、Opera12+和Chrome。
6.语句
ECMAScript中的语句以一个分号结尾;如果省略分号、则由解析器确定语句的结尾。虽然语句的分号不是必需的,但建议任何时候都不要省略它。
var sum = a + b //没有分号也是有效的语句 不推荐 var diff = a - b; // 有效的语句 推荐
加上分号可以避免很多错误(例如不完整的输入)开发人员也可以放心地压缩ECMAScript代码,也可以在某些情况下增进代码的性能。
可以使用C语言风格把多条语句组合到一个代码块中,即代码块以左花括号({)开头,以右花括号(})结尾
if (text) { test = false; alert(test); }
虽然条件控制语句(if语句)只在执行多条语句的情况下才要求使用代码块,但最佳实践是始终在控制语句中使用代码块——即使代码块中只有一条语句。
在控制语句中使用代码块可以让偏码意图更加清晰,而且也能降低修改代码时出错的几率。
7.关键字和保留字
ECMA-262描述了一组具有特定用于的关键字,这些关键字可用于表示控制语句的开始或结束,或者用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。
ECMA-262还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特定的用途,但他们有可能在将来被用作关键字。
关键字和保留字任然不能作为标识符使用,但是现在可以用作对象的属性名。
8.变量
ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据,换句话说,每个变量仅仅是一个用于保存值的占位符而已。
定义变量时要使用var操作符(注意var是一个关键字),后跟变量名(即一个标识符)。
var message;
ECMAScript也支持直接初始化变量,因此在定义变量的同时就可以设置变量的值。
var message = "hi";
在此,变量message中保存了一个字符串值 "hi" 。像这样初始化变量并不会把它标记为字符串类型;初始化的过程就是给变量赋一个值那么简单。因此,可以在修改变量值得同时修改值的类型,
var message = "10"; message = 100;
变量message一开始保存了一个字符串值 "hi" ,然后该值又被一个数字值100取代。虽然不建议修改变量所保存值的类型,但是这种操作是有效的。
用var操作符定义的变量将成为定义改变量的作用域中的局部变量。如果在函数中使用var定义一个变量,那么这个变量在函数退出后就会被销毁
function test() { var message = "hi"; //局部变量 } test(); alert(massage); //错误!
变量message是在函数中使用var定义的。当函数被调用时,就会创建该变量并为其赋值。而在此之后,这个变量又会立即被销毁。因此例子中的下一行代码就会导致错误。
可以省略var操作符,从而创建一个全局变量:
function test() { message = "hi"; //全局变量 } test(); alert(massage); // "hi"
这个例子省略了var操作符,因而message就成了全局变量。这样只要调用过一次test函数,这个变量就有了定义,就可以在函数外部的任何地方被访问到。
虽然省略var操作符可以定义全局变量,但这也不是推荐的做法。因为在局部作用域中定义的全局变量很难维护,如果有意地忽略了var操作符,也会由于相应变量不会马上就有定义而导致不必要的混乱。
可以使用一条语句定义多个变量,只要像下面这样把每个变量(初始化或不初始化均可)用逗号分隔开即可:
var message = "hi", found = false, age = 29;
这个例子定义并初始化了3个变量。同样由于ECMAScript是松散类型的,因而使用不同类型初始化变量的操作可以放在一条语句中完成。
9.数据类型
ECMAScript中有5中简单数据类型(也称之为基本数据类型):Undefined、Null、Boolean、Number和String。还有一种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的。
typeof操作符:
鉴于ECMAScript是松散类型的,因此需要有一种手段来检测给定变量的数据类型——typeof就是负责提供这方面信息的操作符。对一个值使用typeof操作符可能返回下列某个字符串。
"undefined"——未定义;
"boolean"——布尔值;
"string"——字符串;
"number"——数值;
"object"——对象或null;
"function"——函数;
下面是几个使用typeof操作符的例子:
var message = "some string"; alert(typeof message); // "string" alert(typeof(message)); // "string" alert(typeof 95); //"number"alert(typeof null) //object 特殊值null被认为是一个空的对象引用。
这几个例子说明,typeof操作符的操作数可以是尽量(message),也可以是数值字面量。注意,typeof是一个操作符而不是函数,因此例子中的圆括号尽管可以使用,但不是必需的。
Undefined类型:
Undefined类型只有一个值,即特殊的undefined。
未初始化和未声明的变量执行typeof操作符都返回undefined值。
Null类型:
Null类型也只有一个值,就是Null。
null表示一个空对象指针,而这也是使用typeof操作符检测null值时会返回 "object" 的原因。
如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null而不是其他值。这样,只要直接检查null值就可以知道相应的变量是否已经保存了一个对象的引用。
Boolean类型:
Boolean有两个字面值,是true和false。区分大小写,否则是标识符。
要将一个值转换为其对应的Boolean值,可以调用转型函数Boolean()。可以对任何数据类型的值调用Boolean()函数,总会返回一个Boolean值。至于返回值是true还是false,取决于转换值的数据类型和实际值。
各种数据类型及其对应的转换规则:
Number类型:
表示整数和浮点数值(双精度数值)
数值字面量格式:
十进制:可以直接在代码里输入;
八进制(以8位基数):第一位必须是零(0),然后是八进制数字序列(0~7)。如果字面值超出范围,那么前导零将被忽略,后面的数值将被当做十进制数值解析。
十六进制(以16位基数):前两位是0x,后跟任何十六进制数字(0~9及A~F)。字母A~F大小写都可。
var intNum = 55; //整数 var octalNum1 = 070; //八进制的56 var octalNum2 = 079; //无效的八进制数值 ——解析为79 var octalNum3 = 08; //无效的八进制数值 ——解析为8 var hexNum1 = 0xA; //十六进制的10 var hexNum2 = 0x1f; //十六进制的31
在进行算数计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值。
浮点数值:
就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。
不要测试某个特定的浮点数值。因为浮点数值计算会产生舍入误差的问题。
数值范围:
如果超出JavaScript数值范围的值,那么这个数值将被自动转换成特殊的Infinity值。该值就无法继续参与下一次的计算,Infinity不能够参与计算的数值
确定一个数值是不是位于最小和最大的数值之间,可以使用 isFinite() 函数。这个函数位于之间时会返回true。
var result = Numver.MAX_VALUE + Numver.MAX_VALUE; alert(isFinite(result)); //false
尽管在计算中很少出现某些值超出表示范围的情况,但在执行极小或极大数值的计算时。检测监控这些值是可能的,是必需的。
NaN:
即非数值(Not a Number)是一个特殊的数值。用来表示一个本来要返回数值的操作数未返回数值的情况。
两个特点:①任何涉及NaN的操作(NaN/10)都会返回NaN,在多步计算中有可能导致问题。
②NaN与任何值都不相等,包括NaN本身,会返回false。
针对这两个特点,ECMAScript定义了isNaN()函数。这个函数接受一个参数,该参数可以是任何类型。确定这个参数是否 "不是数值"。
isNaN() 在接收到一个值之后,会接受将这个值转换为数值。某些不是数值的值会直接转换为数值,而不能被转换为数值都会导致这个函数返回true。
alert(isNaN(NaN)); //true alert(isNaN(10)); //false(10是一个数值) alert(isNaN("10")); //false(可以被转换成数值10) alert(isNaN("blue")); //true(不能转换成数值) alert(isNaN(true)); //false(可以被转换成数值1)
数值转换:
有3个函数可以把非数值转换为数值:Number()、parseInt()和parseFloat()。第一个可以用于任何数据类型,而另两个函数则专门用于把字符串转换成数值。
Number()函数的转换规则如下:
①如果是Boolean值,true和false将分别被转换为 1 和 0 。
②如果是数字值,只是简单的传入和返回。
③如果是null值,返回0。
④如果是underfined,返回NaN。
⑤如果是字符串,遵循以下规则:
1.如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值。"123"会变成123 ;
2.如果字符串中包含有效的浮点格式,"1.1" ,则将其转换为对应的浮点数值;
3.如果字符串中包含有效的十六进制格式,如 "0xf" ,则将其转换为相同大小的十进制整数值;
4.如果字符串是空的(不包括任何字符),则将其转换为0;
5.如果字符串中包含除上述格式之外的字符,则将其转换为NaN。
⑥如果是对象,则调用对象的valueof()方法,然后依照前面的规则转换返回的值。如果转换结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。
var num1 = Number("Hello world!"); //NaN var num2 = Number(" "); //0 var num3 = Number("0000011"); //11 var num4 = Number(true); //1
parseInt()函数转换规则:
①忽略字符串前面的空格,直至找到第一个非空格字符;
②如果第一个字符不是数字字符或者符号,返回NaN。
③如果字符串以 "0x" 开头且后跟数字字符,则将其当做一个十六进制整数;
④如果字符串以 "0" 开头且后跟数字字符,则会将其当做一个八进制数来解析。
var num1 = parseInt("12345blue"); //12345 var num2 = parseInt(" "); //NaN var num3 = parseInt("0xA"); //10(十六进制数) var num4 = parseInt(22.5); //22 var num5 = parseInt("070"); //56(八进制数) var num6 = parseInt("70"); //70(十进制数) var num7 = parseInt("0xf"); //15(十六进制数)
使用parseInt()解析像八进制字面量的字符串时,ECMAScript3(八进制)和5(十进制)存在分歧。
消除这个困惑,可以为这个函数提供第二个参数:转换时使用的基数(即多少进制)。指定基数会影响到转换的输出结果:
var num1 = parseInt("10", 2); //2(按二进制解析) var num2 = parseInt("10", 8); //8 (按八进制解析) var num3 = parseInt("10", 10); //10(按十进制解析) var num4 = parseInt("10", 16); //16(按十六进制解析)
为了避免错误的解析,建议无论在什么情况下都明确指定基数。
parseFloat函数转换规则:
①第一个小数点有效,第二个小数点无效。后面字符串将被忽略;
②始终都会忽略前导的零;
③十六进制的字符串转换为0;
④只解析十进制值,因此它没有用第二个参数指定数的用法;
⑤如果字符串包含的是一个可解析为整数的数(没有小数点,或者小数点后都是零),parseFloar()会返回整数。
var num1 = parseFloat("1234blue"); //1234(整数) var num2 = parseFloat("0xA"); //0 var num3 = parseFloat("22.5"); //22.5 var num4 = parseFloat("22.34.5"); //22.34 var num5 = parseFloat("0908.5"); //908.5 var num6 = parseFloat("3.125e7"); //31250000
string类型:
用于表示由零或多个16位Unicode字符组成的字符序列,即字符串。字符串可以由双引号(")或单引号(‘)表示。
用双引号表示的字符串和单引号的字符串完全相同,不过双引号开头必须以双引号结尾,单引号也如此。
字符字面量:
String数据类型包含一些特殊的字符字面量,也叫转义序列。用于表示非打印字符,或者具有其他用途的字符。
这些字符字面量可以出现字符串中的任意位置,而且也将被作为一个字符来解析。
字符串特点:
字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。
转换为字符串:
toString()方法:返回相应值的字符串表现。
数值、布尔值、对象和字符串值都有toString()方法。但是null和undefined值没有这个方法。
toString()可以输出以二进制、八进制、十六进制乃至其他任意有效进制格式表示的字符串值。
String()转型函数:这个函数能够让将任何类型的值转换为字符串;
如果值又toString()方法,则调用该方法(没有参数)并返回相应的结果;
如果值是null,则返回 "null";
如果值是nudefined,则返回 "undefined"。
object类型:
对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。
Object类型所具有的任何属性和方法也同样存在于更具体的对象中。
后面章节详细讲解。