语句和表达式
语句和表达式的区别就像英语中的句子和短语的区别一样,多个表达式通过标点符号或者连接词连接成语句
JavaScript中表达式可以返回一个结果值
var a = 3 * 6;
var b = a;
b;
这三行代码都是包含表达式的语句
其中 第一行的3*6 , 第二行的a , 第三行的b都是一个表达式,结果值都是18
var a=3*6和var b=a被称为"声明语句",因为他们声明了变量
a=3*6和b=a(不带var)叫"赋值表达式".
第三行代码只有一个表达式b,同时也是一个语句,被称为"表达式语句"
语句的结果值
每个语句都有一个结果值(undefined也算)
获得结果值最直接的方法是在浏览器控制台中输入语句,默认情况下控制台会显示所执行的最后一条语句的值
如 输入 b=a ,其结果值是赋给b的值
但 规范定义var 的结果值是undefined,如果在控制台中输入var a= 42会得到undefined而不是42
(ES5中其实变量声明算法是有一个返回值的(是一个包含声明变量名称的字符串),但是这个值被变量语句算法屏蔽掉了(for..in除外))
但是在代码中我们无法直接获取这个结果值(赋值表达式,表达式语句除外)
先来看看其他语句
比如代码块{..}的结果值是最后一个语句/表达式的结果
换句话来说,代码块的结果值就如同一个隐式的返回,即返回最后一个语句的结果值
但下面这样的代码无法运行
a = if(true) {
b = 2;
}//Uncaught SyntaxError
因为语法不允许我们获得语句的结果值并赋给另一个变量
那应该怎么获取语句的结果值呢
a = eval(`if(true) {
b = 2;
}`);
a; //2
注意!! 永远不要在实际开发中使用这种方法!!会导致代码运行速度变慢!!(具体原因看这篇)
ES7中有一项提案 "do表达式" (未实装)
a = do {
if(true) {
b = 2;
}
}
类似于这样,do{..}表达式执行一个代码块,并返回最后一个语句的结果值,然后赋值给a
表达式的行为
表达式除了会返回一个结果值,还会有一些附加的行为
比如
var a = 42;
var b = a++;
其中a=42和b=a++(不带var)都是一个赋值表达式
a++首先返回变量a的当前值42(再将该值赋给b),然后将a的值加1(附加行为)
递增运算符++和递减运算符--都是一元运算符(会强制转换为数字),她们既可以用在操作数的前面,也可以用在后面
在前面的时候,如++a,她的附加行为(将a递增)产生在表达式返回结果之前,在后面的时候,则发生在表达式返回结果之后
而++a++则会报错,根据优先级会先执行a++,返回结果值42,然后执行++42,这时候会产生ReferenceError错误
还有一种常见的误解是()能将a++的行为封装起来
然而事实上(a++)还是会先返回原本的值后在执行加1的行为,除非在++后再次对a进行运算
比如(a++,a)
(由于优先级的关系,所以需要放在括号中)
返回的是最后一个语句的结果值,也就是a+1后的值
var a = 42;
var b = (a++, a);
b; //43
标签语句
类似于 foo:fun() 这样的语法叫做标签语句,foo是语句fun()的标签
使用情形如下,continue foo的作用是执行foo循环的下一轮循环,直接写continue的话,则是执行当前循环的下一循环
foo: for(let i = 1; i < 3; i++) {
for(let j = 1; j < 3; j++) {
console.log(i, j);
if(i == j) {
continue foo;
}
}
}
注意, continue ___只能对带标签的循环代码使用
但是 break ___可以对带标签非循环代码使用,作用是挑出标签___所在的循环/代码块
(function() {
foo: {
console.log("hello");
break foo;
console.log("never show");
}
})()