180309 语句

表达式在JS中是短语,语句是JS整句或命令。
JS程序就是一系列可执行语句的集合。

表达式计算一个值,语句用来执行以使某件事情发生。
“使某件事情发生”的一个方法是计算带有副作用的表达式。
另一种“使某件事情发生”的方法是改变语句的默认执行顺序。
(条件语句,循环语句,跳转语句。)

这里写图片描述


表达式语句

一些有副作用的表达式,是可以作为单独的语句的,这种把表达式当作语句的用法也称作表达式语句。

具有副作用的表达式是JS中最简单的语句。

  • 赋值语句
greeting = “Hello” + name;
i *= 3;
  • 递增运算符++,递减运算符- -
counter ++;
  • delete运算符
delete o.x;
  • 函数调用
alert(greeting);
window.close();

复合语句和空语句

JavaScript中还可以将多条语句联合在一起,形成一条复合语句。

  • 使用花括号括起来
  • 语句块结尾不需要分号,块中的原始语句必须以分号结束。
  • 建议缩进,增强代码可读性。
  • JavaSrcipt中没有块级作用域,在语句块中声明的变量并不是语句私有的。

当创建一个具有空循环体的循环时,可以使用空语句。

for (i = 0; i < a.length; a[i++] = 0);

在这个循环中,所有的操作都在表达式a[i++]=0中完成,这里并不需要任何循环体。然而JS需要循环体中至少包含一条语句,因此,这里只使用了一个分号来表示一条空语句。

注意,在 for,while 循环或 if 语句的右圆括号后的分好很不起眼,这很可能造成一些致命bug,而这些bug很难定位到。例如,下面的代码执行结果可能就不是程序作者想要的效果:

if((a == 0) || (b == 0));  // 这一行代码什么也没做。
o = null; // 这一行代码总是会执行。

如果有特殊的目的需要使用空语句,最好在代码中添加注释,这样可以更加清楚地说明这条空语句是有用的:

for(i = 0; i < a.length; a[i++] = 0) /* empty */;

声明语句

var 和 function 都是声明语句,它们声明或定义变量或函数。这些语句定义标识符并给其赋值。

  • var
var i ;
var j = 0;
var p,q;
var greeting = 'hello' + name;
var x = 2.34, y = Math.cos(0.75); 
  1. 如果var语句出现在函数体内,那么它定义的是一个局部变量,其作用域就是这个函数。如果在顶层代码中使用var语句,它声明的是全局变量,在整个JS程序中都是可见的。
  2. var声明的变量是无法通过delete删除的。
  3. 如果var语句中的变量没有指定初始化表达式,那么这个变量的值初始为undefined。
  4. 变量在声明它们的脚本或函数中都是有定义的,变量声明语句会被‘提前’至脚本或函数的顶部。但是初始化的操作则还在原来var语句的位置执行,在声明语句之前变量的值是undefined。
  5. var语句同样可以作为for循环或者for/in循环的组成部分(和在循环之外的变量声明一样,这里声明的变量也会‘提前’)。

  • function

关键字function用来定义函数,写成语句形式

function f(x) {return x + 1} // 含有变量名的语句

函数定义表达式

var f = function(x) {return x + 1} //将表达式赋值给一个变量

在定义函数时,并不执行函数体内的语句,它和调用函数时待执行的新函数对象相关联。


条件语句

  • if,else if 语句

if语句在程序执行过程中创建一条分支,并且可以使用else if来处理多条分支。

if (username == null) // 如果username是null或undefined
username = 'John Doe'; // 对其进行定义
if (!username) username = 'John Doe'; 
// 当username的值为假值时,!username的值为真值,
// 执行条件语句内容。
// 如果username是null,undefined,false,0,'' 或者NaN,
// 那么给它赋一个新值。
  • switch 语句

    所有分支语句依赖于同一个表达式的值时使用。

switch(n){
    case 1:       // 如果 n === 1 ,从这里开始执行
    // 执行代码块1
    break;        // 停止执行switch语句
    case 2:
    // 执行代码块2
    break;
    case 3:
    // 执行代码块3
    break;
    default:
    // 执行代码块4
    break;
}
function convert(x){
    switch(typeof x){
        case 'number':     //将数字转换为十六进制数
            return x.toString(16);
        case 'string':     //返回两端带双引号的字符串
            return '"' + x + '"';
        default:           //使用普通的方法转换其他类型
            return String(x);
    }
}

由于每次执行switch语句的时候,并不是所有的case表达式都能执行到,因此,应当避免使用带有副作用的case表达式,比如函数调用表达式和赋值表达式。最安全的做法就是在case表达式中使用常量表达式。

‘default’ 默认标签,当case都不满足时,执行default语句块。最合理的方式放在末尾,但实际上可以放置在switch语句内的任何地方。


循环语句

  • while语句
var count = 0;
while (count < 10){
    console.log(count);
    count++;
}
  • do/while语句

在循环尾部检测循环表达式,这意味着循环体至少会执行一次。

do{
    statement
}while(expression);
  • for语句
for(initialize初始化;test检测;increment更新){
//第一步先初始化
//然后进行判定
//执行循环语句内容!!!
//更新循环控制
    statement
}
var i,j;
for(i = 0, j = 10; i < 10; i++,j--)
sum += i * j;

循环变量不一定都是数字。

function tail(o){
    for(; o.next; o = o.next)/* empty */;
    // 判断o.next是不是真值来执行遍历
        return o;
    }
  • for/in语句
for (variable in object)
    statement

变量,object表达式计算结果是对象。
在执行过程中,JS解释器首先计算object表达式。如果表达式为null或者undefined,JS解释器将会跳过循环并执行后续的代码。如果表达式是一个原始值将会转换为与之对应的包装对象。否则其本身就是对象。JS会依次枚举对象的属性来执行循环。然而在每次循环之前,JS都会先计算variable表达式的值,并将属性名赋值 给它。


跳转语句

  • 标签语句

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

indentifier:statement

通过给语句定义标签,就可以在程序的任何地方通过标签名引用这条语句。

break和continue是JS中唯一可以使用语句标签的语句。

标签的命名空间和变量或函数的命名空间是不同的,因此可以使用同一个标识符作为语句标签和作为变量名或函数名。

语句标签只有在它所起作用的语句内是有定义的。

  • break 语句

单独使用break语句的作用是立即退出最内层的循环或switch语句。

for(var i = 0; i < a.length; i++){
    if(a[i] == target) break;
}

JS允许break关键字后面跟随一个语句标签:

break labername;// 在关键字break和labelname之间不能换行。
// 因为JS解释器会给语句自动补全省略掉的分号。

当break和标签一块使用时,程序将跳转到这个标签所标识的语句块的结束,或者直接终止这个闭合语句块的执行。

当你希望通过break来跳出非就近的循环体或者switch语句时,就会用到带标签的break语句。即跳出多层次嵌套的循环体逻辑。

// 从标签名开始,以便在报错时推出程序
compute_sum:if(Matrix){
    for(var x = 0; x < martix.length; x++){
    var row = martix[x];
        if(!row) break compute_sum;
            for (var y = 0; y < row.length; y++){
                var cell = row[y];
                if (isnan(cell)) break compute_sum;
                sum += cell;
            }
    }
    success = true;
}
// break语句跳转至此

不管break语句带不带标签,它的控制权都无法越过函数的边界。比如,对于一条带标签的函数定义语句来说,不能从函数内部通过这个标签来跳转到函数外部。

if语句不能单独使用break语句,只能在嵌套时使用。

  • continue 语句

这个语句是转而执行下一次循环。

这个语句同样可以带有标签:

continue labelname

当执行到continue语句的时候,当前的循环逻辑就终止了,随即执行下一次循环,在不同类型的循环中,continue的行为也有所区别:

  1. 在while循环中,在循环开始处的条件判定会重复检测,如果检测结果为true,循环体会从头开始执行。
  2. 在do\while循环中,程序的执行直接跳到循环结尾处,这时会重新判断循环条件,之后会继续下一次循环。
  3. 在for循环中,首先计算自增表达式,然后再次检测test表达式,用以判断是否执行循环体。
  4. 在for\in循环中,循环开始遍历下一个属性名,这个属性名赋给了指定的变量。
  5. 注意continue语句在while和for循环中的区别,while循环直接进入下一轮的循环条件判断,但for循环首先计算其自增表达式,然后判断循环条件。

    • return 语句

函数调用是一种表达式,而所有表达式都有值。函数中的return语句既是指定函数调用后的返回值。

return expression

return语句只能在函数体内出现,如果不是的话会报错。
当执行到return语句的时候,函数终止执行,并返回expression的值给调用程序。

function square(x){ return x*x; }
square(2)     // 调用结果为4

如果没有return语句,则函数调用仅依次执行函数体内的每一条语句直到函数结束,最后返回调用程序。这种情况下,调用表达式大的结果是undefined。

  • throw 语句

    所谓异常(exception)是当发生了某种异常情况或错误时产生的一个信号。
    抛出异常,就是用信号通知发生了错误或异常状况。
    捕获异常是指处理这个信号,即采取必要的手段从异常中恢复。
    throw语句会显式的抛出异常。

throw expression

语句可以抛出一个代表错误代码的数字,或者包含可读的错误消息的字符串。当Js解释器抛出异常的时候通常采用error类型和其子类型。

new Error(‘message’)
function factorial(x){
    // 如果输入参数是非法的,则抛出一个异常
    if (x > 0throw new Error(‘x不能是负数’);
    // 否则,计算出一个值,并正常地返回它
    forvar f = 1; x > 1; f *= x, x- -)/*empty*/;
    return f;
}

当抛出异常时,js解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。

  • try/catch/finally 语句

这条语句是js的异常处理机制。

try语句定义了需要处理的异常所在的代码块。
catch从句跟随在try语句之后,当try语句块内发生异常,调用catch内的代码逻辑。
finally块内放置清理代码,不管try块中是否产生异常,finally块内的逻辑总是会执行。

try {
    // 通常来讲,这里的代码会从头执行到尾而不会产生任何问题,
    // 但有时会抛出一个异常,要么是由throw语句直接抛出异常
    // 要么是通过调用一个方法间接的抛出异常
}
catch(e){
    // 当且仅当try语句块抛出了异常,才会执行这里的代码
    // 这里可以通过局部变量e来获得对Error对象或者抛出的其他值的引用,
    // 这里的代码块可以基于某种原因处理这个异常,也可以忽略这个异常,
    // 还可以通过throw语句重新抛出异常
}
finally{
    // 不管try语句块是否抛出了异常,这里的逻辑总是会执行,终止try语句块的方式有:
    // 1)正常终止
    // 2)通过break,continue或return语句
    // 3)抛出一个异常,异常被catch从句捕获
    // 4)抛出一个异常,异常未被捕获,继续向上传播
}

其它语句类型

  • with 语句

with语句用于临时扩展作用域链。

with(object)
statement

这条语句将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态。

with语句的缺点:优化难,运行慢。

  • debugger 语句

该语句可以产生一个断点。JS的执行会停止在断点的位置,这时候可以使用调试器输出变量的值,检查调用栈等。

  • ‘use strict’

‘ use strict ’ 是ES5引入的一条指令。指令不是语句,很接近。

‘ use strict ’ 指令和普通语句之间的区别:

  1. 它不包含任何语言的关键字,指令仅仅是一个包含一个特殊字符串直接量的表达式,对于那些没有实现ES5的JS解释器来说,它只是一条没有副作用的表达式语句。将来的ES标准希望将use用来做关键字。
  2. 它只能出现在脚本代码的开始或者函数体的开始,任何实体语句之前。但不一定出现在脚本的首行或函数体的首行。因为 ‘ use strict ’ 指令之后或之前都可能有其他字符串直接量表达式语句,并且JS的具体实现可能将它们解析为解释器自有的指令。在脚本或者函数体内第一条常规语句之后字符串直接量表达式语句只当做普通的表达式语句对待;它们不会当做指令解析,它们也没有任何副作用。

使用指令后的代码是严格代码。严格代码以严格模式执行。

严格模式的内容:

  1. 禁止with语句
  2. 所有变量先声明后赋值
  3. 调用的函数(不是方法)中的一个this值是undefined。(在非严格模式下,调用的函数中的this值总是全局对象)。可以利用这种特性来判断JS是否支持严格模式:
var hasStrictMode = (function (){"use strict";return this===undefined}());
发布了44 篇原创文章 · 获赞 2 · 访问量 5031
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章