03 语法

作者: 将军肚 | 来源:发表于2018-07-08 15:56 被阅读0次

    ES7中有一项 do表达式 提案,类似

    var a , b;
    a = do {
        if(true){
            b = 4 + 38;
        }
    };
    a; // 42
    

    其目的是将语句当作表达式来处理,从而不需要将语句封装为函数再调用return 来返回值。

    5.1.2 表达式副作用

    最常见的有副作用的表达式是函数调用:

    function foo() {
        a = a + 1;
    }
    var a = 1;
    foo();   // 结果值: undefined 。副作用: a 的值被改变
    

    可使用,语句系列逗号运算符将多个独立的表达式语句串联成一个语句:

    var a = 42, b;
    b = ( a++, a );
    a;  // 43
    b; // 43
    

    a++, a 中第二个表达式a在a++之后执行,结果为43,并被赋值给b。

    var a, b, c;
    a = b = c = 42;
    

    链式赋值常常被误用,例如var a = b = 42; 看似和前面的例子差不多,实则不然。如果变量b没有在作用域中象var b 这样声明过,则var a = b =c = 42 不会对变量b进行声明。在严格模式中会产生错误,或者会无意中创建一个全局变量。

    5.1.3 上下文规则

    1. 大括号
      (1)对象常量
    // 假定bar() 已定义
    var a = {
        foo: bar()
    }
    

    {..}被赋值给a,因为它是一个对象常量。

    (2)标签
    如果将上例中的 var a = 去掉会发生什么情况呢?

    {
            foo: bar()
        }  
    

    {..}在这里只是一个普通的代码块。语法是完全合法的,特别是和let在一起时非常有用。

    但foo: bar() 这样奇怪的语法为什么也合法呢?

    这里涉及JS中一个不为人知的特性,叫做"标签语句",foo是语句bar() 的标签(后面没有;)

    如果JS有goto语句,理论上可使用goto foo跳转到foo处执行。但JS不支持goto。

    然而JS通过标签跳转能实现goto的部分功能。continue和break语句都可带一个标签,因此能像goto那样进行跳转。

    // 标签为foo的循环
    foo: fro ( var i = 0;  i<4;  i++) {
        for(var j = 0; j<4;  j++){
            // 如果j和i相等,继续外层循环
            if(j == i) {
                  // 跳转到foo的下一个循环
                  continue foo;
            }
            // 跳过奇数结果
            if( (j*i) % 2 == 1 ){
                // 继续内层循环(没有标签的)
                continue;
            }
            console.log( i, j );
        }
    }
    
    

    continue foo 并不是指“跳转到标签foo所在位置继续执行”,而是"执行foo循环的下一轮循环"。

    带标签的循环跳转一个更大的用处在于,和 break __ 一起使用可实现从内层循环跳转到外层循环。

    // 标签为foo的循环
    foo: for( var i = 0;  i < 4;  i++){
        for(var j=0; j<4; j++){
            if( (i*j) >= 3){
                console.log("stopping!", i, j);
                break foo;
            }
            console.log(i, j);
        }
    }
    
    

    标签也能用于非循环代码块,但只有break才可以。我们可对带标签的代码块使用break __,但是不能对带标签的非循环代码块使用continue __,也不能对不带标签的代码块使用break;

    // 标签为bar的代码块
    function foo(){
        bar: {
            console.log("Hello");
            break bar;
            console.log( "never runs" );
        }
        console.log( "world" );
    }
    foo();
    // Hello
    // World
    
    1. 对象解构
    function getData() {
        return {
            a: 42,
            b: "foo"
        }
    }
    var {a, b} = getData();
    
    console.log(a, b);  // 42 "foo"
    
    

    {a, b} = ..就是ES6中的解构赋值,相当于下面的代码:

    var res = getData();
    var a = res.a;
    var b = res.b;
    
    

    {..}还可用作函数命名参数的对象解构,方便隐式地用对象属性赋值:

    function foo({a, b, c}){
        // 不再需要这样:
        // var a = obj.a,  b = obj.b,  c =obj.c
    
        console.log(a, b, c);
    }
    foo({
        c: [1, 2, 3],
        a: 42,
        b: 'foo'
    })
    
    
    

    5.2.1 短路

    对&& 和 || 来说,如果从左边的操作数能够得出结果,就可忽略右边的操作数。我们将这种现象称为"短路"。

    function doSomething(opts){
        if(opts.cache || primeCache()){
            //..
        }
    }
    
    

    5.5 函数参数

    function foo( a = 42, b = a + 1){
        console.log(a, b);
    }
    foo();   // 42 43
    foo( undefined );  // 42 43
    foo( 5 );  // 5 6
    foo( void 0, 7);  // 42 7
    foo( null );  // null 1
    

    相关文章

      网友评论

          本文标题:03 语法

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