书接上文,来看看JavaScript的基本语法:
1 语句
和大部分的解释性语言(比如Python)一致,JavaScript也是以行(line)为执行单位的,也就是一行一行的执行,一般情况下,一行就是一个语句(statement)。
语句是指为了完成某种任务而进行的操作,如下:
let a = 2 + 2;
这里使用了let声明变量a,然后将2 + 2的运算结果赋值到变量a。
2 + 2是表达式(expression),就是一个为了得到返回值的计算式(数学意义上的算式)。
语句和表达式的区别即:
- 语句主要为了进行某种操作,一般不需要返回值;
- 表达式则是为了得到返回值,一定会返回一个值——凡是JavaScript预期为值的地方,都可以使用表达式
语句以分号结尾,一个分号就表示语句的结束;多个语句可以写在同一行内:
let a = 2 + 2; let b = 'abc';
分号前如果没有任何内容,JavaScript引擎也会认为其生效,即空语句:
;;;
纯表达式不需要分号结尾,一旦添加,JavaScript引擎会将表达式识别为语句,这样会产生一些没有任何意义的语句:
2 + 2;
'abc';
如上只能单纯产生2个值,由于没有任何变量可供承载这些值,故而并没有任何意义。
2 变量
2.1 概念
变量是对值的显性引用:变量即为值起名,然后引用这个名字就等于引用这个值,这个名字也就是变量名:
let a = 0;
这里let是声明变量的命令,与其有类似功能的有var和const;const和let是在ECMAScript 6才引入的命令,目的是为了减少原来只有一个var声明变量而产生的诸多问题,具体区别可以后文再说,这里只需要知道在基础环境下,var和let是可以互换使用的,而const则是声明常量——即不可再次修改的变量——的命令。
上面的语句表示先声明变量a,并在变量名a和数值0之间建立引用关系,称为将数值0赋值给变量a。
和Python相同,JavaScript的变量名是区分大小写的,也即a和A是两个完全不同的变量。
变量的声明和赋值其实是分开的两个步骤,上面的代码其实际的步骤如下:
let a;
a = 0;
如果仅仅声明变量但没有赋值,则该变量的值是undefined——这是JavaScript特有的值,表示“未定义”。
打开任意一个桌面浏览器,按键盘上的“F12”,打开开发者工具,切换到console标签,试着输入如下两条语句,看看结果:
let a;
a
结果如图:
留意:如果声明变量的时候忘记写var、let或者const,直接赋值的话也是有效的:
b = 0;
// 基本等同于
let b = 0;
但这里有两点考虑:
- 不写声明命令的做法,不利于表达意图;
- 所创建的变量往往是全局变量,容易污染整个代码环境;
所以建议一定使用声明命令来声明变量。
可以使用同一个声明命令来声明多个变量:
let a, b, x, y;
由于JavaScript是动态类型语言,所以其变量的类型并没有限制,可以虽然更改类型;比如声明时是文本,之后可以根据需要直接修改为数值,如下:
let a = 'test';
a = 1;
同一个变量名只可以声明一次,如果使用let进行声明,这种重复声明会报错,可参考下面的截图;而使用var进行声明则不会报错,单纯声明将没有作用,但是声明的同时赋值则会赋值成功:
let x = 1;
// 这里会报错
let x;
let x = 5;
var x = 1;
// 这里不会报错
var x;
var x = 5;
x // 5
如下两图:
2.2 变量提升
*如果使用let或者const进行变量声明,不会存在变量提升的现象,一旦采取下文当中的方式,将会报错。
当使用var进行变量声明时,JavaScript引擎的工作方式:
- 先解析代码,获取所有被声明的变量;
- 然后一行一行的运行;
这样,所有变量的声明语句,都会被提升到代码的头部,就是所谓的变量提升(hoisting)——如下述代码:
console.log(a);
var a = 1;
结果:
实际执行步骤等同于:
var a;
console.log(a);
a = 1;
因为变量提升的原因,在控制台记录a这个变量的时候并没有赋值,故此结果是undefined。
由于IE并不支持采用ECMAScript 6的let和const进行变量声明,建议一定要先进行变量声明,避免变量提升的现象。
3 标识符
标识符(identifier)也就是用来识别各种值的合法名称。最常见的就是变量名,以及后面会提到的函数名;它对大小写敏感。
标识符的命名规则如下:
- 首字符可以是任意Unicode字符以及美元符号$和下划线_;
- 之后的字符除了上述字符,还可以使用数字0-9。
故此下面都是合法标识符:
- test
- _temp
- $mine
- über0
- 变量1
这些则是非法标识符:
- 1a
- *test
- x+b
- -temp
同时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
4 注释
代码中被JavaScript引擎忽视的部分就是注释,一般用来对代码进行解释;现在也有很多通过识别注释生成API文档的工具,所以良好的开发习惯就是一定要合理的使用注释,可以降低后续开发工作量。
JavaScript提供两种注释的写法:
// 单行注释
/* 这是
多行
注释
*/
此外,由于JavaScript曾经需要兼容HTML的注释,所以目前为止,HTML的注释方式也是合法的单行注释:
x = 1; <!-- x = 2;
--> x = 3;
如上,只有 x = 1会执行,其他的部分都被注释掉了:
其中-->只有在行首才会被当作单行注释,否则会被当作正常运算,如下:
代码当中的n --> 0实际上变成了n-- > 0,因此变成了自减是否大于0的检测,则可以输出倒数结果。
5 区块
使用大括号将多个相关语句组合到一起,被称为区块(block)。
对于变量声明命令var来说,区块不构成单独的作用域(scope);而let则只会在区块中生效,在区块外部不存在,如下图:
在 JavaScript 语言中,单独使用区块并不常见,区块往往用来构成其他更复杂的语法结构,比如for、if、while、function等。
如图:
6 条件语句
JavaScript提供if和switch结构用来进行条件判断,即只有满足预设的条件才会执行对应的语句:
6.1 if结构
if结构先判断一个表达式的布尔值(boolean),然后根据布尔值的真伪执行不同的语句。
布尔值就是各种开发语言当中通用的两个特殊值,在JavaScript当中,使用true表示真,false表示伪。
if结构的基本形式包括两种:
- 单语句执行判断:
// if (布尔值) 语句;
if (x > 0) console.log(x);
- 多语句执行判断:
/* if (布尔值) {
语句区块;
}
*/
if (x > 0) {
let y = x + 1;
console.log(y);
}
建议总是在if语句中使用大括号,这样方便插入语句。
6.2 if...else结构
if代码区块的后面,还可以使用else区块,表示不满足条件时需要执行的代码:
/* if () {
满足条件的语句;
} else {
不满足条件的语句;
}
*/
if (x > 0) {
let y = x + 1;
console.log(y);
} else {
console.log(x);
}
也可以通过将多个if...else语句连写在一起,进行更复杂的判断,如下:
let x, y, z;
/*
一些其他的代码……
*/
if (x > 0 && z === 5) {
y = x + 1;
} else if (x === 0 && z < 5){
y = z - 1;
} else {
y = x + z;
}
console.log(y);
6.3 switch结构
多个if...else连在一起使用的时候,可以转为使用更方便的switch结构:
switch (fruit) {
case "banana":
// ...
break;
case "apple":
// ...
break;
default:
// ...
}
上面的代码根据变量fruit的值来选择执行对应的case;如果所有的case不符合,则执行最后的default部分。其中break是指代在执行完当前case代码块之后跳出switch结构,如果没有则会顺序执行而不跳出。
6.4 三元运算符? :
开发语言中通用的三元预算符JavaScript也是可以使用的,即:
// 条件? 表达式1 : 表达式2;
let n = 10;
let even = (n % 2 === 0) ? true : false;
上面这段代码等同于:
let n = 10;
let even;
if (n % 2 === 0) {
even = true;
} else {
even = false;
}
也就是说,三元运算符可以看作是if...else的简写形式。
7 循环语句
循环语句用于重复执行某个操作,有如下形式:
7.1 while循环
while语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块:
/* while (条件) {
语句;
}
*/
let i = 0;
while (i < 100) {
console.log(i);
i += 1;
}
7.2 for循环
for语句是另一种形式,可以指定循环的起点、终点和终止条件:
/* for (初始表达式; 条件表达式; 递增/递减表达式) {
语句;
}
*/
for (let i = 0; i < 100; i++) {
console.log(i);
}
- 初始表达式(initialize):确定循环变量的初始值,只在循环开始时执行一次。
- 条件表达式(test):每轮循环开始时,都要执行这个条件表达式,只有值为真,才继续进行循环。
- 递增/递减表达式(increment):每轮循环的最后一个操作,通常用来递增/递减循环变量。
7.3 do...while循环
do...while循环和while循环类似,但它会先运行一次循环体,然后判断循环条件,确认是否继续执行下去:
/* do {
语句;
} while (条件);
*/
let i = 0;
do {
console.log(i);
i++;
} while (i < 100);
7.4 break和continue语句
break语句用于跳出代码块或循环,如下,当i等于10就立刻跳出循环。
let i = 0;
while (i < 100) {
console.log(i);
i++;
if (i === 10) break;
}
continue语句用于立即中止本轮循环,返回循环结构的头部开始下一轮循环,如下只有i为奇数时才会输出,如果为偶数则直接进入下一轮循环。
let i = 0;
while (i < 100) {
i++;
if (i % 2 === 0) continue;
console.log(i);
}
如果存在多重循环,不带参数的break语句和continue语句都只针对最内层循环。
7.5 标签(label)
JavaScript 语言允许语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置,一般与break或者continue配合使用:
// 标签: 语句
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
这是一个双重循环,在break后面加上了top,表示满足条件时,直接跳出双层循环。
执行结果如图:
与continue配合则是如图效果:
8 其他
在接下来的部分当中,会着重使用ECMAScript(后文简称ES)6以上的版本特性,而需要考虑IE或者旧版本ES5的时候会单独提出。
评论
发表评论