JS从0开始(七)闭包深入、立即执行函数、逗号运算符

113 阅读2分钟

一.立即执行函数

1.定义

立即执行函数 ( IIFE ):自动执行,执行完成以后立即释放
IIFE: immediately-invoked function expression

2.写法

立即执行函数有两种写法:

  • (function( ){
    语句; }) ( );
  • (function(){
    语句;  } ( ) ); //两种方法都可以,W3C建议第二种

所以说括号括起来的任何东西即使不是表达式也都会变成表达式(详细看第四点)

和普通函数一样,立即执行函数执行以后就销毁了

3. 立即执行函数传递实参的方式

  <script>
    (function (a, b) {
            console.log(a + b);
        }(2, 4));
    
    </script>

4.实例

  <script>
       function test() {
            console.log(1);
        } (); //语法错误
    </script>
    <script>
        (function test() {
            console.log(1);
        } ()); //能执行
    </script>
    <script>
       var test = function test() {
            console.log(1);
        } (); //能执行
    </script>

(1).从第2、3个代码块中可知:一定是表达式才能被执行

从以上第1、2、3个代码块中可知: 括号包起来的变成了表达式才能执行

(2).立即执行函数的销毁

②这里自动执行了,执行完就销毁,所以最后test1 输出undefined 所以说立即执行函数 后面声明的函数名(如test) 会自动忽略

(3)变为表达式的方法

   + function test(){
    console.log(10);
   }();//能执行
   
   1 || function test(){...} //能执行
   0 && function test(){...} //能执行

所以说 在function之前 加运算符(+ - / * %等 甚至|| &&)等会变成表达式从而可以执行函数

二.逗号运算符

逗号运算符只会输出逗号最后面一个

 <script>
        var num = (2 - 1, 6 + 5, 24 + 1, 66, 77, 1 + 2)
        console.log(num);
 </script>

三.闭包的深入

(1)经典面试题

<script>
   function test() {
            var arr = [];
            for (var i = 0; i < 10; i++) {
                arr[i] = function () {
                    document.write(i + " ")
                }
            }
            return arr;
        }
        var myArr = test();
        for (var j = 0; j < 10; j++) {
            myArr[j]();
        }
     }
  </script>    

第一个for循环可以理解为:

<script>
   function test() {
            var arr = [];
            var i = 0;               /for循环拆开
            for ( ;i < 10;) {
                arr[i] = function () {
                    document.write(i + " ")
                }
                 i++;               /for循环拆开
            }
            return arr;
        }
  </script>    

for循环遇到里面小函数的时候,先把自己的弄完 再执行这个小函数
但是return arr;的时候形成了闭包
所以到最后 i 放到大函数的AO里面时已经变成了10,这时再运行小函数时自然返回10
以后看到 return 的时候都要想到闭包

上述函数想返回0到9的话,可以选择使用立即执行函数

<script>
   function test() {
           for(var i = 0; i < 10; i++){
           (function(){
                document.write(i+" ");
           })();
           }
        }
  </script>    

或者:

<script>
   function test() {
           for(var i = 0; i < 10; i++){
           (function(j){ (接受下面传过来的实参)
           arr[j] = function(){
                document.write(i+" ");
                }
           })(i); //每次接收for循环的i
           }
           return arr;
        }
        
    ······
    ······
  </script>    

(2)面试题2

 <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>

    <script>
        var oLi = document.querySelectorAll("li");
        for (var i = 0; i < oLi.length; i++) {
            oLi[i].onclick = function () {
                console.log(i);   /输出5
            }
        }
    </script>

而上式去掉函数语句输出为:

 for (var i = 0; i < oLi.length; i++) {
                console.log(i);   /输出0 1 2 3 4 
                }

即一般for()循环里面出现函数 都会产生闭包。 等它执行完时,还不会执行,只有我onclick 时,它才会执行,此时for循环已经结束,i = 5

(3)面试题3

 <script>
       var a = 10;
       if(function b(){}){
         a += typeof(b);
       }
       console.log(a); //输出10undefined
    </script>

function b(){}在if的括号里面, 变成了表达式, 所以此时忽略函数名 b ,语法错误,输出undefined

但是if里边有判断符的话 如  if(1 < function b () { } ) 此时不输出后面的语句
1 > function b(){} 此时不输出后面的语句
1 == function b(){} 此时不输出后面的语句
0 < function b(){} 此时不输出后面的语句
0 && function b(){} 此时不输出后面的语句
0 || function b(){} 此时输出后面的语句
1 && function b(){} 此时输出后面的语句

总结:当表达式内只是函数时输出后面的语句  而里面有判断符时不会输出     逻辑判断符有时会输出后面的语句