本文介绍JS的基本语法。
表达式和语句
每一行JS代码都是一个表达式(Expression)或者语句(Statement)。
这两个词看似相同,实则不然。
简单来说,表达式和语句的区别是前者一般会产生值(函数不调用产生值,调用产生返回值),后者可能有也可能没有值。
表达式产生一个(返回)值,语句操作一个(返回)值。当然并不绝对,二者都可以在某些情况下做到另外一个做的事情。
语句一般会改变环境(声明新变量,赋值等)。
//这些是表达式
1 //它的值是1
1 + 2 //它的值是3
3 > 2 //它的值是true
console.log //它的值是一个函数
console.log(3) //它的返回值是undefined
//这些是语句
var a = 1 //声明语句3步:声明变量的类型,命名,赋值。它也有值undefined
a = 1 //它也有值1
标识符
变量的名字叫做标识符。可以使用任意Unicode字符命名变量,包括英文字母,符号如_$
,数字等。但须遵循一定的规范,以下的标识符是不合法的,不可以为变量命名:
- 以数字开头。
- 含有运算符
+-*/|&~!%.<>
中的任意一个。反斜杠\
除非后面的内容能表示一个Unicode字符,否则也不可使用。 - 含有引号。包括单引号
'
,双引号"
,反单引号。 - 含有大中小括号,包括左右括号。
()[]{}
都不可以出现。 - 含有语句关系的符号,包括连接符号逗号
,
,分隔符号分号;
。 - 保留字。例如
var
,this
,function
等等。不同的环境的保留字可能不同。
非英文字符,例如中文可以作为标识符,但强烈不推荐使用。
JS保存下来的标识符实际是Unicode字符。因此命名为\u0061
的变量可以用a
访问,反之亦然。
标识符应当尽可能通俗易懂,不要随意使用拼音或者缩写。
一些注意点
- JS大小写敏感。
a
和A
、object
和Object
是不同的东西。 - 不影响断句的情况下,空格一般不影响表达式的执行。
1+2
和1 + 2
和1+ 2
是一样的。 - 回车一般不影响多个语句的连续执行。但是
return
表达式不可直接加空格。原因在JS历史一文中有提及:
解释器会给每个语句自动补上分号
;
,因此容易产生意想不到的错误。var a = function(){ return { i=1 }; } console.log(a());
上述代码返回的并不是一个对象,而是
undefined
。因为解释器给return
一行补上了分号。实际运行的是:var a = function(){ return; //多了一个分号 { i=1 }; } console.log(a());
区块
用大括号{}
包裹起来的一行或多行代码称为区块。代码块会生成一个新的作用域
。这在部分情况下会出现访问变量的问题,之后深入学习时会碰到。
例子(先不深入讨论):
{
var a = 3;
console.log(a) // 3
}
console.log(a); // 3
{
let a = 3;
console.log(a) // 3
}
console.log(a); // 报错,因为let声明的变量的作用域是块级作用域。
注释
//这是单行注释
/*这是多行注释
不要把代码用中文再解释一遍,不重要的注释不要写
重要的注释要及时更新
不要用注释发泄你的不满
把遇到的bug,容易踩的坑,一些不容易理解的特殊需求写出来
*/
分割符号
逗号,
表示这一句语句还未结束。分号;
表示前一个语句结束,后一个语句开始。
条件语句
if-else语句
语法形式为:
if(一个表达式或者语句){
// 表达式或者语句产生真值时执行的一段代码
}else{
// 表达式或者语句产生假值时执行的一段代码
}
if-else语句根据括号内的表达式或语句执行后是否产生一个真值,执行不同的代码。
若代码块中只有1行代码,大括号可以省略,不过不推荐。
else语句跟在if语句后面,当表达式或语句产生假值时执行。如果不需要,也可以不写。
不写{}
的情况下if
语句会把后面一行代码当作表达式为真时执行的代码。
示例1:
var b = 1;
if(b > 3){
b = 2;
}else{
b = 3
}
console.log(b) //3
//因为一开始的b不满足b>3,if后的语句不执行,else的语句执行,b=3
示例2:
var a = 1;
if(a === 3) //已知if语句后面不跟代码块,表达式为真时,会执行之后的一句语句。
console.log(a); //分号
console.log("aaa");
//输出aaa,因为分号连接的两个语句是两句。if只管到console.log(a)。
var a = 1;
if(a === 3)
console.log(a), //逗号
console.log("aaa");
//什么都不输出,因为逗号连接的两个语句算作一句。
并不是只有true
才是真值。有很多种情况都能产生真值:
产生真值的例子
//布尔值true
if(true)
//一个值为布尔值true的表达式
if(3>2)
//非空字符串
if('false'),if('t r u e')
//任意不为0的数字
if(2), if(0.5), if(-1)
//在非IE浏览器中,window.all是一个假值
if(!window.all)
//一个产生真值的语句
if(a=1)
需要注意的是最后一种情况中:括号里的语句是会被实际执行的。例子:
var a = 0;
if(a=1){
console.log("Yes") // Yes
}
console.log(a) // 1,因为a=1被实际执行了。
产生假值的情况有:
产生假值
//布尔值false
if(false)
//一个产生布尔值false的表达式
if(3<2)
//数字0
if(0), if(-0)
//null
if(null), if(a=null)
//undefined
if(undefined), if(b=undefined)
//NaN
if(NaN)
//空字符串
if(''), if(""), if(``)
上面的例子可以变态一点:
var a = 3;
if(a = 0){
a = 2;
console.log("Yes")
}
//不会输出"Yes",因为a=0的值是0,
//同时,a=0被执行了,因此a=0
console.log(a) // 0
switch
多个if-else语句嵌套的另一种写法。很容易写错,慎用。
var fruit = "banana";
switch(fruit){ //fruit是一个待比较的变量,会依次和下面的case比较。
case "banana":{
console.log("1");
break; //千万别忘了break,否则会继续执行下一个比较。
};
case "apple":{
console.log("2");
break; //千万别忘了break,否则会继续执行下一个比较。
};
default:{ //以上case都不满足时执行的代码。
console.log("0"); //default可以不写break。
}
}
//输出:1
循环语句
while语句
while(表达式){
// 语句
}
首先判断while语句的表达式, 当表达式的值为真时执行其中的代码,然后重新判断表达式的值是否为真,如此循环,直到表达式的值为假。表达式为假或者语句中令循环终止,循环结束。
只有1行语句时,可以不写大括号。
var i = 0
while(i < 100){
i++;
}
console.log(i) // 100
for语句
语法:
for(初始语句; 表达式; 循环一次后的操作){
// 语句
}
首先执行初始语句,然后判断表达式是否为真,是则执行循环体内的语句,然后执行循环一次后的操作。接着按照判断表达式的真假——循环——循环后操作——判断表达式真假的方式循环。表达式为假或者语句中令循环终止,循环结束。
初始语句只在最开始执行1次,一般是用来声明一个计数器并赋初始值。
示例:
for(var i = 0; i < 5; i++){
console.log(i)
}
//依次输出0,1,2,3,4.
continue和break
continue
用来跳过当前循环体中剩下的语句,重新判断表达式的真假并决定是否进入下一次循环。break
用于结束整个循环。
for(var i = 0; i < 3; i++){
console.log(i);
if(i > 0){
break;
}
console.log("break");
}
//输出0 break 1
for(var i = 0; i < 3; i++){
console.log(i);
if(i > 0){
continue;
}
console.log("continue");
}
//输出0 continue 1 2
常用运算符
三元运算符
if-else的简化版。语法形式为:表达式1?表达式2:表达式3
。
当表达式1
的值为真,执行表达式2
,否则执行表达式3
。
3>2?a = 2:console.log("false") //3>2,因此执行表达式2,声明了一个全局变量a,并赋值为2.
短路运算符
可以把多个表达式串接在一起,取第一个符合条件的值。
与短路算符&&
:第一个产生假值的表达式的值,都产生真值则为最后一个表达式产生的值。
var a = 2+5 && 'null' && undefined && false //undefined
或短路算符||
:第一个产生真值的表达式的值,都产生假值则为最后一个表达式产生的值。
var a = [] || 'null' || undefined || false //[]
Label
label语句用来标记后面的一个代码块。相当于给一个代码块命名。语法:
label名: 语句 //给label命名时遵循标识符规范。
label语句可以和break和continue结合使用。和break使用时,控制终止哪个循环体。和continue使用时,控制从哪个循环体继续执行。
例1:
foo: {
console.log(1);
break foo; //这个代码块到此为止,不再继续执行
console.log('这一行不会输出');
}
console.log(2);
//输出结果为1 2
例2:
loop1:
for(var i=0;i<2;i++){
console.log('i=' + i);
loop2:
for(var j=3;j<5;j++){
console.log('j=' + j);
loop3:
for(var k=6;k<8;k++){
console.log('k=' + k);
if(k === 7){
break loop2; //表示终止loop2循环,接下来从loop1开始继续循环。
//continue loop2 //表示从loop2开始继续循环。
}
}
}
}
// 如果是break loop2 输出为i=0 j=3 k=6 k=7 i=1 j=3 k=6 k=7
// 如果是continue loop2 输出为i=0 j=3 k=6 k=7 j=4 k=6 k=7 i=1 j=3 k=6 k=7 j=4 k=6 k=7