美文网首页《JavaScript 权威指南(第六版)》学习笔记
《JavaScript 权威指南(第六版)》三——语句

《JavaScript 权威指南(第六版)》三——语句

作者: 静候那一米阳光 | 来源:发表于2017-02-23 16:30 被阅读0次

    第五章:语句

    2017.02.23

    语句

    语句(statement)是JavaScript整句或命令。

    表达式计算值,语句用来执行以使某件事发生。

    表达式语句

    表达式语句(expression statement):具有副作用的表达式是JavaScript最简单的语句。

    赋值语句

    i*=3;
    

    递增递减++ --

    counter++;
    

    delete运算符

    delete o.x;
    

    函数调用

    alert(greeting);
    window.close();
    

    复合语句和空语句

    用花括号将多条语句结合在一起,形成一条复合语句(compound statement)。希望多条语句被当做一条语句使用时,使用复合语句来替代。

    {
        x=Math.PI;
        cs=Math.cos(x);
        console.log("cos(π)="+cx);
    }
    

    语句块的结尾不需要分号。

    空语句(empty statement)允许包含0条语句。

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

    声明语句

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

    var

    var name_1 [=value_1] [,...,name_n[=value_n]]
    

    function

    var f=function(x){return x+1;} //①
    function f(x){return x+1;} //②
    

    function语句的花括号是必须的,即使只包含一条语句(不同于while if等语句)。

    函数声明语句通常出现在JavaScript代码的最顶层,也可以潜逃在其他函数体内。但在嵌套时,函数声明只能出现在所潜逃函数的顶部。函数定义不能出现在if语句,while循环或其他任何语句中。(有些JS的实现允许出现语句的地方都可以进行函数声明,但是不同的实现在细节处理方式上有很大差别,因此将函数声明放在其他的语句内的做法并不具备可移植性。)

    ①中使用var,只有变量声明提前,初始化代码还在原位。②函数名称和函数体均提前。

    条件语句

    条件语句是通过判断指定表达式的值来决定执行还是跳过某些语句。

    if/else if

    if(expression){
        //
    }
    else if{
        //
    }...{
        //
    }else{
        //
    }
    

    没有花括号时,else总是和最近的if语句相匹配。所以建议使用花括号,即使分支只有一条语句。

    switch

    此处的case匹配使用===恒等运算符比较。

    switch(expression){
        case expression1:
            statements1;
            [break;]
        case expression2:
            statements2;
            [break;]
        case expression3:
            statements3;
            [break;]
        ...
        default:
            statements;
    }
    

    循环

    while

    while(expression){
        statements
    }
    

    do/while

    do {
        statements
    }while(expression)
    

    for

    for(initialize;test;increment){
        statements
    }
    

    相当于

    initialize;
    while(test){
        statements
        increment;
    }
    

    死循环

    for(;;)
    

    相当于

    while(true)
    

    for/in

    for(varibale in object){
        statement
    }
    

    用for in循环遍历对象属性成员:

    for(var p in o){
        console.log(p+":"+o[p]);//p是属性名,o[p]是属性值
    }
    

    注意:只要for/in 的variable值可以当做赋值表达式的左值,它可以是任意表达式。每次循环都会计算这个表达式。

    将对象的所有属性名复制到一个数组中:

    var o={x:1,y:2,z:3};
    var a=[],i=0;
    for(a[i++] in o);
    

    枚举数组索引:

    > var a=[1,2,,,,4]
    undefined
    > del
    0
    1
    5
    

    for/in循环并不会遍历对象的所有属性,只有"可枚举"(enumerable)的属性才会遍历到。JavaScript语言核心所定义的内置方法就不是"可枚举的"。对象可以继承其他对象的属性,集成的自定义属性也可以枚举出来。如果for/in循环体删除了还未枚举的属性,那么这个属性将不会再枚举到。如果循环体定义了新属性,这些属性通常不会被枚举到。

    属性枚举的顺序

    实际上,主流浏览器厂商的JavaScript实现是按照属性定义的先后顺序来枚举简单对象的属性,先定义的先枚举。如果使用对象直接量的形式创建对象,则将按照直接量中属性的出现顺序枚举。

    More 关于枚举顺序

    跳转

    break:跳转到循环或者其他语句的结束。
    continue:终止本次循环的执行并开始下一次循环的执行。
    return:让解释器跳出函数体的执行,并提供本次调用的返回值。
    throw:触发或者抛出一个异常,与try、catch、finally语句一同使用。

    标签语句

    identifier:statement
    

    通过break,continue跳转。break和continue是JavaScript中唯一可以使用语句标签的语句。

    示例

    mainloop:while(token!=null){
        //...
        continue mainloop;
    }
    

    用作标签的identifier必须是合法的标识符,不能使保留字。标签的命名空间与变量函数的命名空间不同,因此可以使用同一个额标识符作为语句标签和作为变量名或函数名。语句标签只有在它所起作用的语句内是有定义的。一个语句标签不能喝它内部的语句标签重名,但在两个代码段不相互嵌套的情况下可以出现同名的语句标签。带有标签的语句还可以带有标签。

    outerloop: 
    for (var i = 0; i < 10; i++) { 
        innerloop:  
        for (var j = 0; j < 10; j++) { 
            if (j > 3){ 
              break; 
            } 
            if (i == 2) { 
              break innerloop; 
            } 
            if (i == 4) { 
              break outerloop; 
            } 
        document.write("i=" + i + " j=" + j + "<br>"); 
        } 
    } 
    

    break 语句

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

    break;
    

    break 关键字后面紧跟一个语句标签。

    break labelname;
    

    当break和标签一块使用时,程序将跳转到这个标签所标识的语句块的结束,或者直接终止这个闭合语句块的执行。当没有任何闭合语句块指定break所用的标签,这时会产生一个语法错误。当使用这种形式的break语句时,带标签的语句不应该是循环或者switch语句,因为break可以跳出任何闭合的语句块。这列的语句可以是花括号括起来的一组语句,使用同一个标签来标识这一组语句。

    break和labelname之间不能换行。因为换行会在break后面补分号。

    break无论带不带标签,都无法越过函数的便捷。在函数内部无法通过标签跳转到函数外部。

    continue 语句

    执行下一次循环。

    continue;
    

    continue后面紧跟一个语句标签。

    continue labelname;
    

    不管continue带不带标签,只能在循环体内使用,否则会报语法错误。

    带标签的continue语句可以用在嵌套的循环中,用以跳出多层次嵌套的循环体逻辑。

    continue和labelname之间不能换行。

    return 语句

    函数中的return语句是指定函数调用后的返回值。

    return expression;
    

    只能在函数体内出现,否则语法错误。

    如果没有return语句。函数一次执行函数体内的每一条语句直到结束,表达式结果返回undefined。

    return语句不必带有expression,这样函数也会返回undefined。

    return和expression之间不能有换行。

    throw 语句

    异常(exception)是当发生了某种异常情况或错误时产生的一个信号。抛出异常,就是用信号通知发生了错误或异常装潢。捕获异常是指处理这个信号,即采取必要的手段从异常中恢复。在JavaScript中,当产生运行时错误或者程序使用throw语句就会显式地抛出异常。使用try/catch/finally语句可以捕获异常。

    throw expression;
    

    例如:

    function f(x){
        if(x<0) throw new Error("x 不能是负数");
        return x;
    }
    f(-1);//Error: x 不能是负数
    

    当抛出异常时,JavaScript解释器会当即停止当前正在执行的逻辑,并跳转至就近的异常处理程序(try/catch/finally语句段)。如果抛出异常的代码块没有相关联的catch一句,解释器会检查更高层的闭合代码块,以此类推,直到找到一个异常处理程序位置。
    如果没有处理语句,异常将向上传播到调用该函数的代码。这样,异常就会沿着JavaScript方法的语法结构和调用栈向上传播。如果没有任何异常处理程序,JavaScript将把异常当做程序错误来处理,并报告给用户。

    try/catch/finally 语句

    各语句块都需要用花括号括起来。不能省略。

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

    catch子句中的标识符具有块级作用域,只在catch内有定义。不管try代码执行了多少,只要try语句中有一部分代码执行了,finally从句就会执行。

    More

    其他语句

    with 语句

    域链(scope chain),一个可以按序检索的对象列表,通过它可以进行变量名解析。

    with 可用于临时扩展作用域链。

    with (object)
    statement
    

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

    严格模式中禁止使用with。使用with语句的JavaScript代码难于优化,运行更慢。

    例如:

    document.forms[0].address.value
    
    with(document.forms[0]){
        name.value="";
        address.value="";
        email.value="";
    }
    

    等价于

    var f=document.forms[0];
    f.name.value="";
    f.address.value="";
    f.email.value="";
    

    只有在查找标识符的时候才用到作用域链,创建新的变量的时候不适用。

    with(o) x=1;//如果对象o有属性x,那么代码给属性赋值。如果没有,则等价于不含有with语句的情景。给局部变量或全局变量赋值或初始化全局变量并赋值。
    

    debugger 语句

    debugger语句通常什么也不做。调试程序可用并且运行时,JavaScript将会以调试模式运行。实际上,此语句用于产生断电,JavaScript代码执行将会停止在短点的位置。

    function f(o){
        if (o===undefined) debugger;
    }
    

    "use strict"

    ES5引入的指令。指令不是语句(但非常接近于语句)。

    • 不包含任何语言的关键字。指令仅仅是一个包含一个特殊字符串直接量的表达式。(单引号或双引号)
    • 只能出现在脚本代码的开始或者函数体的开始、任何实体语句之前。

    目的是说明(脚本或函数中)后续的代码将会解析为严格代码。如果顶层使用"use strict",那么它们就是严格代码。eval()内代码同样是严格代码。

    • 严格模式禁止使用with语句
    • 严格模式中,所有变量都要先声明。如果个未命名的变量,函数,函数参数,catch从句参数或全局对象的属性赋值,都会抛出引用错误异常。
    • 严格模式中,调用的函数中的一个this值是undefined。非严格模式下this总是全局对象。可以用这种特性判断JavaScript是否支持严格模式。var hasStrictMode=(function(){"use strict";return this===undefined}());
    • 严格模式中,传入eval()的代码不能调用程序所在的上下文中声明变量或定义函数。变量和函数的定义是在eval()创建的新作用域中,这个作用域在eval()返回时就弃用了。
    • 严格模式中,函数里的arguments对象拥有传入的函数值的静态副本。非严格模式中,arguments对象具有"魔术般"的行为,arguments里的数组元素和函数参数都是指向同一个值的引用。
    • 严格模式中,delete跟随非法的标识符(变量,函数,函数参数)时,会抛出一个语法错误异常。(非严格模式下,delete什么也没做并返回false);试图删除一个不可配置的属性将抛出一个类型错误异常(非严格模式中不会报错)。两种模式下删除非左值都返回true。
    • 严格模式中,函数声明中存在两个及以上同名的参数会产生语法错误(非严格模式中不会报错,后者覆盖前者):实际Chrome测试,严格模式下不会报错,后者覆盖前者。
    • 严格模式中,函数声明中存在两个或多个同名参数会报错(非严格模式下,会覆盖)
    • 严格模式中,不许晕使用八进制整数直接量。
    • 严格模式中,eval和arguments当做关键字,值不可以更改。不能给其赋值,不能声明为变量、用做函数名或用作catch块标识符。
    • 严格模式中限制了对调用栈的检测能力。 arguments.caller和arguments.callee都会抛出类型错误异常。严格模式函数同样具有calle和arguments属性,访问这两个属性时将抛出类型错误异常(有一些JavaScript的实现在费严格模式里定义了这些非标准的属性)

    示例,chrome58 dev 下

    【严格模式下】

    <script>
        "use strict";
        function f(){
            return this;
        }
        console.log(f());//输出 undefined
        console.log(delete 1===true);// true
        var o={x:1,x:2};
        var o=123;
        console.log(o);//123
        function ff(x,x){
            return (x+x);
        } //Uncaught SyntaxError: Duplicate parameter name not allowed in this context
        console.log(ff(1,2));
        var m={x:2}
        function c(o){
            o.x=1;
        };
        c(m);
        console.log(m);//Object {x:1}
    </script>
    

    【非严格模式下】

    <script>
        function f(){
            return this;
        }
        console.log(f());//输出 window对象
        console.log(delete 1===true);// true
        var o={x:1,x:2};
        var o=123;
        console.log(o);//123
        function ff(x,x){
            return (x+x);
        } //4
        console.log(ff(1,2));
        var m={x:2}
        function c(o){
            o.x=1;
        };
        c(m);
        console.log(m);//Object {x:1}
    </script>
    

    chrome 58 dev下

    > (function(){"use strict";return this===undefined}());
    true
    

    node 6.9.5下

    > (function(){"use strict";return this===undefined}());
    true
    
    语句语法小结

    相关文章

      网友评论

        本文标题:《JavaScript 权威指南(第六版)》三——语句

        本文链接:https://www.haomeiwen.com/subject/cbybwttx.html