句法基础

课后整理 2020-12-20

句法定义了JavaScript的逻辑结构,包括词、句和段的基本规则和特性。本节将介绍JavaScript语言的句法基础,了解JavaScript的代码结构。

认识词、句和段

JavaScript语法体系体现了一种词、句、段的层次结构。简单说明如下:

在JavaScript程序中,常用大括号来划分段落结构,大括号拥有封装代码和逻辑的功能,由此形成一个独立的段落结构。

JavaScript使用大括号将多个相关的语句组合在一起,称为“区块”(block)。

与大多数编程语言不一样,JavaScript的区块不构成单独的作用域(scope)。也就是说,区块中的变量与区块外的变量,属于同一个作用域。

{
  var a = 1;
}
a // 1

上面代码在区块内部,声明并赋值了变量a,然后在区块外部,变量a依然有效,这说明区块不构成单独的作用域,与不使用区块的情况没有任何区别。所以,单独使用的区块在JavaScript中意义不大,很少出现。区块往往用来构成其他更复杂的语法结构,比如for、if、while、function等。

【示例1】下面这些结构都可以形成独立的段落。

{
    // 对象结构
}
function (){
    // 函数体
}
if (){
    // 条件体
}
for (){
    // 循环体
}
while (){
    // 循环体
}
switch (){
    // 多条件结构
}
with (){
    // 作用域
}
try{
    // 异常处理
}

段落结构包含的内容可以是一个或多个句子。段落起始标记({)前面可以添加修饰词,如域谓词(with)、逻辑谓词(if、while、for、switch等)、函数谓词(function fn(arg))等。

句子就是由词构成的完整的可执行命令。在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中,词语之间必须使用分隔符进行分隔,否则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语句分隔符,用来分隔不同的语句。

【示例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;                      // 错误的分行显示

安全的方法应该按如下所示分行显示。这样每一行都不能形成独立的语义。

ar i = a ? 1
     : b ? 2
     : c ? 3
     : 4;                           // 安全的分行显示

【提示】

JavaScript并不是在所有换行处都自动填补分号,只有在缺少了分号就无法正确解析代码的时候,JavaScript才会填补分号。因此,如果当前语句和随后的非空格字符不能当成一个整体来解析的话,JavaScript就在当前语句行结束处填补分号。

例如,如果第一行语句以 (、[、/、+或-结束,那么它极有可能和第二行语句合在一起解析。类似的还有return、break和continue语句。

也有例外:在涉及++和--运算符的时候,这些运算符可以作为表达式的前级,也可以当做表达式的后缀。如果将其用做后缀表达式,它和表达式应当在同一行。否则,行尾将自动填补分号,同时++和--将会作为下一行代码的前级操作符并与之一起解析。例如:

x
++
y

将被解析为x;++y;,而不是x++;y;。

大括号

大括号是语句分段标识,也可以构建数据结构(在对象章节将详细讲解)。

【示例1】下面代码使用大括号定义一个对象直接量,其中包含多个“名/值”对,名称与值之间通过冒号分隔,每个“名/值”对之间通过逗号分隔。

// 使用大括号定义对象类型的数据结构
var house1 = {
    bigBedroom: "大卧", 
    smallBedroom: "小卧",
    diningRoom: "餐厅",
    livingRoom: "客厅",
    toilet: "卫生间"
}

【示例2】下面代码定义一个函数,在函数中嵌套了一个switch条件结构。

// 定义函数对象结构
function house2(o){
    switch(o){  // 定义多条件结构体
        case "bigBedroom" :
            return "大卧";
            break;
        case "smallBedroom" :
            return "小卧";
            break;
        case "diningRoom" :
            return "餐厅";
            break;
        case "livingRoom" :
            return "客厅";
            break;
        case "toilet" :
            return "卫生间";
    }
};
alert(house2("smallBedroom"));     // 调用函数

JavaScript 不支持使用大括号定义块状作用域,不过支持函数作用域,不允许外界直接访问函数内变量。在循环结构和条件结构中,大括号可以允许循环语句和条件语句包含更多的执行语句。