js中需要特殊注意的点

149 阅读3分钟

alert()也算一次运算

老样子,举例说明

例1:
    /*
     * EC(G)变量提升
     * var a;function b(){}  =>0x0000   [[scope]]:EC(G)
     */
    var a = 1;
    function b(c){
        /*
         *EC(b)
         *  作用域链:<EC(b),EC(G)>
         *  形参赋值:c = 2【c是私有变量】
         *  变量提升:--
         */
        alert(c+a++);//3
        //++在变量后边,那么先算其他运算,在算++,由于alert也算一次运算,所以弹出c+a,2+1=3,
        然后在算a++,那此时alert已经弹完了,所以a++只是在系统中运算,不会表现出来
    };
    b(2);
    console.log(a);//这是输出a,已经是a++运算之后的结果了,所以是2

匿名函数具名化

例2:
    /!*
     * EC(G)变量提升
     *   var b; 
     *   自调函数不进行变量提升,执行时候直接创建堆和执行上下文
     *!/
    var b = 10;
    (function b() {
        /!*
         * 自执行函数本身应该是匿名函数(还有函数表达式或者回调函数等都是匿名),只不过为了
         * 保证良好编码习惯,我们经常给本应是匿名的函数 “具名化”(起个名字)
         *    1.这个名字只能在函数内部被调用,函数外面用不了(可以理解为是私有变量)
         *    2.这个名字的变量,在函数内部,值也是不能被修改的(改了也没用,还是代表函数)
         * EC(AN) 
         *!/
        b = 20;
        console.log(b); //=>函数本身
    })();
    console.log(b); //=>10 
 

    (function AAA() {
        // console.log(AAA); //=>函数本身(这样后期在递归调用的时候,可以直接基于AAA执行
        即可,无需再使用arguments.callee了【arguments.callee在严格模式下不支持】)
     
        AAA = 1000;
        console.log(AAA); //=>函数本身
    })();
    console.log(AAA); //=>Uncaught ReferenceError: AAA is not defined 

例3:
    (function AAA() {
        /!*
         * 如果是基于VAR/LET/FUNCTION等再次声明的操作单独处理,会把这个具名化的名字改为正常
         * 的私有变量,也就是名字不再代表函数了 
         *!/
        // console.log(AAA); //=>Uncaught ReferenceError: Cannot access 'AAA' before initialization
        let AAA = 100;
        console.log(AAA); //=>100
    })();
 
    /* (function AAA() {
        console.log(AAA); //=>函数(输出1的)
        function AAA(){console.log(1)}
        console.log(AAA); //=>函数(输出1的)
    })(); */
 
    /* (function AAA() {
        console.log(AAA); //=>undefined
        var AAA = 200;
        console.log(AAA); //=>200
    })(); */

函数形参带ES6默认值,函数体中重复声明会多形成一个块级作用域

  • 函数执行的时候,如果设置了形参变量(“并且”部分形参变量设置了ES6中的形参赋值默认值),这样在形成私有上下文的时候,会多创建一个块级上下文(函数的大括号单独看做一个块级上下文)

  • 第二个限制条件是:当前形参变量在大括号中被重新声明过

     例4:
         /!*
          * EC(G)中的变量提升 
          *   var x;
          *   function func(x,y){...}  =>func=AAAFFF000
          *!/
         var x = 1;
         function func(x, y = function anonymous1() {x = 2}) {
             /!* 
              * EC(FUNC)私有上下文
              *   形参赋值:x=5  y=BBBFFF000(anonymous1匿名函数) [[scope]]:EC(FUNC)
              *   变量提升:由于形参带ES6默认值,此时函数体内重新声明了形参,所以会形成一个块级作用域
              * EC(BLOCK)块级作用域
              *   形参赋值:--
              *   变量提升:会把EC(FUNC)私有上下文的形参赋值拷贝一份到这里
              *!/
             var x = 3;
             var y = function anonymous2() {x = 4};
             //此时块级作用域中的x、y与私有上下文的形参x、y是分开的,自己是自己的
             y(); //=>Y执行是让ANONYMIOUS2执行,里面的x = 4是块级作用域中的x
             console.log(x); //=> 4
         }
         func(5);
         console.log(x); //=>1