1.

    1. function a() {
    2. let a = 1;
    3. let b = a++;//这里a变成了2
    4. console.log(a);//2
    5. console.log(b);//1
    6. console.log(a++ + ++a);//6
    7. console.log(a++ + a++ + a++);//15
    8. console.log(a++);
    9. }
    10. a();

    根据运算符优先级,a++ + ++a中相当于(a++) + (++a),a++的特性是先使用a进行运算,因此左边的式子为2+4,因此输出 6.
    下面的是同理,式子等同于4+5+6,因此输出15。
    而最后的console.log输出的是7,函数中最后a等于8。

    2.

    1. console.log(typeof 1);
    2. console.log(typeof []);//object
    3. console.log(typeof new Function())//function
    4. console.log(typeof 1 - "1");//NaN
    5. console.log(typeof 1 + "1");//number1
    6. console.log(typeof 1 + 1);//numver1

    typeof运算符的优先级高于加减乘除,且返回的是字符串,因此会出现上述结果。

    3.

     var foo = { n: 1 };
          (function (foo) {
            console.log(foo.n);
            foo.n = 3;
            var foo = { n: 2 };
            console.log(foo.n);
            foo.n = 4;
            console.log(foo.n);
          })(foo);
          console.log(foo.n);
    

    涉及知识

    • foo是一个对象传入的是对象地址,因此在函数中改变foo会改变外部的对象。
    • 函数中,var的声明会提前,但是赋值不提前,但是这时只有变量的声明,没有变量的赋值,优先级低于形参,因此第一个log输出的是1。如果这个时候进行了赋值,那么输出的就不是1了。
    • 第二个log前重新声明了一个foo对象,因为是在函数中,所以是局部变量,与外部传入的foo不同,因此之后的对象修改和输出都是基于局部变量。因此输出2,4。
    • 最后一行的log输出语句,因为函数中唯一修改外部foo对象只有3,因此输出3。

    4.

    let a = 1;
        function fn1() {
          function fn3() {
            let a = 3;
            fn2();
          }
          let a = 2;
          return fn3;
        }
        function fn2() {
          console.log(a);
        }
        let fn = fn1();
        fn();
    

    执行fn函数的时候,一直向下执行fn()\fn3()\fn2(),因为JS使用的是词法作用域(静态作用域),因此执行fn2()时,a使用的是定义时的环境中的1。