啃一啃犀牛书--语句

啃一啃犀牛书–语句

语句类型大致如下:

  • 表达式语句
  • 符合语句和空语句
  • 声明语句
  • 条件语句
  • 循环语句
  • 跳转语句
  • 其他

如果单纯看上面的这些语句类型可能会一脸懵逼,或者图片(黑人问号),但是在日常的代码中,可能我们大多都是用到了,只是你可能不知道这个到底该如何说。

表达式语句

例如常见的赋值语句,是一类比较重要的表达式语句。

1
var a = 'hello world';

递增运算符,递减运算符

1
2
i ++;
++i;

delete 运算符

1
delete o.x;

还有函数调用

1
2
3
alert(1111);
window.close();
window.open();

复合语句和空语句

我们在声明变量的时候,可是使用逗号进行分割声明多个,也就是将多个表达式串联起来形成表达式,
针对上面的复合也简单理解将多个语句组合在一起成为复合语句。

1
2
3
4
5
6
{

let x = Math.PI;
cx = Math.cos(x);
console.log('cx')
}

像上面的代码,一般我们都是写在某个方法或者函数里面看起来会协调一点,这是一个语句块,但是要注意一点,js是没有块级作用域的,
如果这样写的话,里面如果有声明变量,它并不是语句块私有的,这儿其实也就牵扯到了es6里面关于let,const所声明的变量是拥有块级作用域的,在之前的章节
有说到过,在这里就不再说了,贴个链接,方便移步查阅ECMAScript6 入门

空语句可能最常见的场景就是在循环语句或者条件语句中出现,如下:

1
2
3
4
5
var a = [];
for(var i = 0;i < 10;a[i++] = 0)/*enpty*/;
for(var i = 0;i < 10;i++){
a[i] = 0;
}

这样初始化一个长度位10的数组,第一个for循环,跟第二个for循环是一样的,只是写法不同,在第一个for循环中,注意尾部的分号,
里面就相当于一条空语句。一般情况下,最好还是加上注释,这样也方便其他人理解。否则,如果你下面又跟了一条循环,
别人在看代码的时候,这个可读性就真的有点差了。

声明语句

在es5中,声明语句只有两个关键字,一个var,一个function,在es6中新增加了let,const,class,import。
要注意他们之间的一些细微差别哦~(变量提升)。

这里面需要注意的点是,我们定义函数的时候,是不能出现在if语句,while语句或者其他语句之中,但是实际上浏览器并没有做这样的限制。
但是这种基本上还是与我们的本意不太贴切,我们肯定是期望函数或者变量等都是先声明再调用,如同let,const等,如果不先声明,就会报错。
这一点也基本上可以算是糟粕里面的了。

条件语句

我们常用的条件语句一般是if,switch。这两个。这两个语句倒是真心没有太多可以说的,平时大家肯定已经用的不能再烂了,这里提一个与之相关的。
在js蝴蝶书,JavaScript语言精粹中,提到了”==”与”===”,因为这个,基本上是我们在if中必用的运算符了。
在前面的章节说过这两个区别,原因就是”==”这个里面会涉及到类型转换,而且有些判断可能与我们的心理预期并不一致(比如null==undefined)
所以道格拉斯已经将这个列为糟粕,而在现在的一些编译器中,如果你这样写的话,也会给你提示。

这里面可能还要再提到switch语句的穿越的问题。

除非你能明确地中断流程,否则每次条件判断后都会穿越到下一个case条件。

上面的话引自蝴蝶书p111。

这里面我们就要很好的控制中断过程,也就是break。因为如果是这里面除了问题,导致出现穿越可能会使我们的bug排查起来比较困难。

循环语句

主要是while,for。如果你有学过其他的语言,或者听说过,你也应该了解,一般的循环语句就这两个喽。
我一般常用的for循环。但是循环语句的时候,有时候还是要根据当前的业务场景来使用比较好。

1
2
3
4
5
6
7
8
9
10
11
var a = 0;
while(a<10){
console.log(a);
a++;
}
for(var i = 0;i< 10 ;i++){
if(i>10){
break
}
console.log(i)
}

上面两端代码的输出结果是一样的,但是很好看出,上面的代码看起来更简洁一点。一般在循环需要有条件限制的时候,while可能会简洁一点。
但是我们如果需要遍历数组之类的,可能for循环的会让我们更轻松一点。

1
2
3
4
var a = [1,2,3,4,5];
for(var i = 0;i < a.length;i++){
console.log(a[i])
}

这里面还有do while循环,for in 循环,do while循环与while类似,只不过它是在循环尾部而不是顶部检测,这
就意味着你的循环至少会执行一次。
for in 虽然也使用了for关键字,但是它和常规的for循环并不一样。

1
2
3
4
5
6
7
8
var a = {
x:1,
y:2,
z:3
}
for(index in a ){
console.log(index +':'+a[index])// x:1 y:2 z:3
}

在前面的章节有说道关于for in 这个in其实是遍历了对象属性,对于数组来说,这个index就是下标。
我们将上面的代码改一下:

1
2
3
4
var a = [1,2,3]
for(index in a ){
console.log(index +':'+a[index])//0:1 1:2 2:3
}

因为in是遍历对象的属性,在数组中,这个属性就指的是索引了。还有一个差别,for in 循环并不会遍历对象的所有属性,
只有”可枚举”的属性才会被遍历。(ps:所有的对象都拥有方法toString(),但是for in 并不会把它枚举)

跳转语句

这里面提到了一个之前不曾知道的东西:标签语句。

语句是可以添加标签的,标签是由语句前的标识符和冒号组成:

1
identifier: statement

这里有个限制,break和continue是js中唯一可以使用语句标签的语句。示例代码:

1
2
3
mainloop: while(token !=null){
continue mainloop;
}

暂时留个坑吧,这个地方多研究一下,回来再补上。

break,continue,return,throw。这几个应该都不太陌生。

break立即退出最内层的循环或switch语句。当然,也只有在这种情况下,使用break才是合法的。
continue 语句用法与break类似,只是含义不一样,它不是退出,而是转而执行下一次循环。
在蝴蝶书中,将continue列为糟粕,理由如下:

continue语句跳到循环的顶部。我发现一段代码通过重构移除 continue语句之后,性能都会得到改善。

但是究其原因,我发现我现在并不懂,只能当我对js的理解更深刻的时候再来解答这个问题了。

接下来就是return了,这个语句你应该使用的最多。

1
return expression

return 语句只能在函数体内出现,如果不是的话会报语法错误。当执行到return语句的时候,函数终止执行,并返回expression的值给调用程序。
return语句也可以单独使用,这样函数也会向调用程序返回undefined。

throw语句,在js中,当产生运行时错误或者程序使用throw语句时就会显式地抛出异常。当抛出异常时,js解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。
try/catch/finally语句是js的异常处理机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
try{
//这里的代码会从头执行到尾而不产生任何副作用
//如果出现异常,可以通过throw来抛出异常,或者进入下一个catch语句
// throw new Error('lalalal')

}
catch(e){
//当且仅当try语句抛出异常,才会执行到这里,这里的参数e其实就是throw所抛出的内容
//这里的e就是上面的'lalalal'
}
finally{
//不管try语句是否抛出了异常,这里的逻辑总是会执行
}

其他

with 语句。首先,并不建议使用with语句,其次在严格模式中,是禁用with语句的,在蝴蝶书中,也是将其列为糟粕。

debugger语句。这个跟浏览器里面打断点类似了,当程序执行到这个地方的时候,就会进入断点。
我所使用到的场景是这样的,我们的某段js是通过请求得来的,我在浏览器里面断点根本打不上,无奈就在请求来源里面加上debugger,这样
就可以打上断点,方便调试了。

“use strict”它并不能算是一条语句,是一条指令。它规定下面的代码将以严格模式执行。ECMAScript5中的严格模式是该语言的一个受限制子集。
关于它的一些区别,有挺多,这里列出最为重要的三条:

  • 在严格模式中禁止使用with语句
  • 在严格模式中,所有的变量都要先声明,如果给一个未声明的变量、函数、函数参数、catch从句参数或全局对象的属性赋值,将会抛出一个引用错误异常(
    在非严格模式终酿,这种隐式声明的全局变量的方法是给全局对象添加一个新属性)
  • 在严格模式中,调用的函数(不是方法)中的this值是undefined。(在非严格模式中,调用的函数中的this值总是全局对象)。可以利用这种特性来判断js实现是否支持严格模式
    1
    var hasStrictMode = (function(){"use strict";return this===undefined}());

本章已经算是啰嗦完了,本想着不抄书的,但是发现有些地方书上的总结还是比较好的。同事在看问题的时候发现,但从一本上书上的理解可能并不太透彻,
看来后面的章节,可能要结合多本书并配合google来进行诠释了。