普通的函数在全局定义之后是存在GO中的,是不释放的,在想调用的时候就能调用 有些函数只需要运
行一次之后再也不会执行 -> 立即执行函数

(1)立即执行函数 (初始化函数)

IIFE -> immediately-invoked function expression D2262 G7085

  1. - 自动执行
  2. - 执行完自己销毁


///

//写法一:
(function () {

})()

//写法二
(function(){

}());

闭包demo

    function test() {
        var arr = [];
        for(var i =0;i<10;i++){
            arr[i] = function(){
                document.write(i +' ');
            }
        }
        return arr; //返回arr数组时 i等于10 每次function(){} 赋值给arr[i] 但是未赋值
    }
    var myArr = test();
    // console.log(myArr);
    for(var j = 0;j<10;j++){
        myArr[j]();
    }
//输出10个10

解决方案一 立即执行函数

    function test() {
        // var arr = [];
        for(var i =0;i<10;i++){
            (function(){
                document.write(i +' ');
            }());
        }
    }
    test();

解决方案二 改变传参

    function test() {
        var arr = [];
        for(var i =0;i<10;i++){
            arr[i]=function(num){
                document.write((num) +' ');
            }
        }
        return arr; 
    }
    var myArr = test();
    // console.log(myArr);
    for(var j = 0;j<10;j++){
        myArr[j](j);
    }

解决方案三 立即执行并传参

    function test(){
        var arr = [];
        for(var i = 0;i < 10;i++){
            (function(j){
                arr[i]=function(){
                    document.write(j +' ')
                }
            })(i);
            }
            return arr; //返回arr数组时 i等于10 每次function(){} 赋值给arr[i] 但是未赋值
    }
    var myArr = test();
    for(var j = 0;j<10;j++){
        myArr[j]();
    }

demo2

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
</body>
<script>
    var oLi = document.querySelectorAll('li');
    for (var i = 0; i < oLi.length; i++) {
        oLi[i].onclick = function () {
            console.log(i);
        }
    }
</script>

demo3

    var fn = (
        function test1(){
            return 1;
        },
        function test2(){
            return '2';
        }
    )();
    console.log(typeof(fn)); //stirng

demo4

    var a =10;
    if(function b(){}){  //()括号的作用:加括号里的内容转换成表达式 表达式忽略函数名 => function (){} =>undefined
        a+=typeof(b);
    }
    console.log(a);  // 10undefined

课后作业

闭包写法

1.累加器

    // 单独返回数组写法
    function fnx(){
        var num = 0;
        function add(){
            num++;
            // console.log('运行加法运算'+num);
            return num;
        }
        function sub(){
            num--;
            // console.log('运行减法运算'+num);
            return num;
        }
        return [add,sub];
    }
    var arr = fnx();
    console.log(arr[0]());
    console.log(arr[0]());
    console.log(arr[1]());
    console.log(arr[0]());

    //整体返回数组写法
    function fnx2(){
        var num = 0;
        var optarr = [
            function add(){
                num++;
                console.log(num);
            },
            function sub(){
                num--;
                console.log(num);
            }
        ]
        return optarr;
    }
    var arr2 = fnx2();
    arr2[0](10);
    arr2[1](10);

// 整体返回对象写法
    function fn3(){
        var num = 0;
        var optobj = {
            add: function () {
                num++;
                console.log(num);
                // return num;
            },
            sub:function (){
                num--;
                console.log(num);
                // return num;
            }
        }
        return optobj;
    }
    var  obj = fn3();
    obj.add();
    obj.sub();

//单独返回对象写法
    function fn4(){
        var num = 0;
        function add(){
            num++;
            console.log(num);
        };
        function sub(){
            num--;
            console.log(num);
        };
        return {add,sub};
    }
    var obj2 = fn4();
    obj2.add();
    obj2.sub();

2. 一个班级,学生名字保存在一个数组里,两个方法写在函数中的一个对象中,第一个方法加入班级,第二个方法离开班级,每次加入或离开

//都需要打印新的学生名单
  //数组写法  
    function fnstudent(){
        var name = [];
        var stuopt = [
            function add(newname) {
                name.push(newname);
                console.log(name);
            },
            function sub(newname) {
                var index = name.indexOf(newname);
                console.log(index);
                if(index>-1){
                    name.splice(index,1);
                }
                console.log(name);
            }
        ]
        return stuopt;
    }
    var objstudent = fnstudent();
    objstudent[0]('ming');
    objstudent[0]('xyf');
       objstudent[1]('ming');

//对象写法
    function fnstudent2(){
        var name = [];
        var stuopt = {
             add:function(newname) {
                name.push(newname);
                console.log(name);
            },
             sub: function(newname) {
                var index = name.indexOf(newname);
                console.log(index);
                if(index>-1){
                    name.splice(index,1);
                }
                console.log(name);
            }
        }
        return stuopt;
    }
    var objstudent = fnstudent2();
    objstudent.add('ming');
    objstudent.add('xyf');
    objstudent.sub('xyf');

遍历查找的写法
    function fnstudent2(){
        var name = [];
        var stuopt = {
             add:function(newname) {
                name.push(newname);
                console.log(name);
            },
             sub: function(newname) {
                 for(var i=0;i<name.length;i++){
                     var item = name[i];
                     if(item === name){
                         students.splice(i,1);
                     }
                 }
                console.log(name);
            }
        }
        return stuopt;
    }
    var objstudent = fnstudent2();
    objstudent.add('ming');
    objstudent.add('xyf');
    objstudent.sub('xyf');