Javascript闭包

203 阅读3分钟

#高阶函数

        // 高阶函数 以函数作为参数或者以函数作为返回值,则就是高阶函数
        function demo() {
            // setTimeout(function () {
            //     fn()
            // }, 2000)
            return function(){
                console.log("1111")
            }
        }
        // demo函数称为高阶函数
        var f1 = demo();

#闭包

        // 闭包

        // 这种算是不是太明显的闭包
        // function fn1(){
        //     var num = 10;
        //     function fn2(){
        //         console.log(num)
        //     }
        //     fn2()
        // }
        // fn1()

        // 称之为闭包
        // 闭包的剖析
        // 首先要有函数嵌套函数
        // 然后内部函数使用了外部函数的变量或者参数
        // 导致使用的变量或者参数不会被直接释放
        // 按照正常的思路fn1下面没有代码执行了num就要被释放掉
        // 这样就形成了闭包
        function fn1(){
            var num = 10;
            return function(){
                console.log(num)
            }
        }

        var fn2 = fn1()
        fn2()

#闭包2

    <ul>
        <li>刘德华</li>
        <li>郭富城</li>
        <li>蔡徐坤</li>
        <li>鹿晗</li>
    </ul>
    <script>
        var liList = document.querySelectorAll("li")

        for (var i = 0; i < liList.length; i++) {
            // 因为for循环很快的创建了四个定时器
            // 所以定时器打印不出liList
            // console.log(liList[i])
            (function (i) {
                setTimeout(function () {
                    console.log(liList[i])
                }, 3000)
            })(i)
        }

#点击显示相应的索引值

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

        // 点击相应的li,打印出来索引值,并且打印li里面的内容
        var liList = document.querySelectorAll("li")
        // liList.forEach(function(item,index){
        //     // console.log(item)
        //     item.onclick = function(){
        //         console.log(item)
        //         console.log(index)
        //     }
        // })

        // for(var i = 0; i < liList.length; i++){
        //     liList[i].index = i
        //     // console.log(liList[i].index)
        //     liList[i].onclick = function(){
        //         // 点击的时候for循环早已经执行完毕了
        //         console.log(i)
        //         console.log(this.index)
        //     }
        // }

        // // 使用闭包的方式解决i会在执行完毕变为最大的
        // for(var i = 0; i < liList.length; i++){
        //     // onclick这个属性需要的是一个函数
        //     // 但是这个是自执行函数就不是一个函数了
        //     // 每当onclick被赋值一次就会保存一个i值
        //     liList[i].onclick = (function(i){
        //         // console.log(i)
        //         return function(){
        //             console.log(i)
        //         }
        //     })(i)
        // }

        liList.forEach(function(item,key){
            // console.log(key)
            item.onclick = function(){
                console.log(key)
            }
        })

#封装

        // (function(window){
        //     var count = 0;
        //     var obj = {
        //         add: function() {
        //             count++
        //         },
        //         sub: function(){
        //             count--
        //         }
        //     }
        //     // return obj
        //     window.obj = obj;
        //     // console.log(window.obj)
        // })(window)

        // obj.add()
        // obj.sub() 
        // // 就是拿不到count值 形成了封装 变量的私优化


        // function showBiBao() {
        //     for (var i = 0; i < 5; i++) {
        //         setTimeout(function timer() {
        //             console.log(i)
        //         }, 1000);
        //     }
        //     console.log(i)
        // }
        // // 会输出什么
        // // 这种闭包只形成了一次闭包现象
        // showBiBao()

        // 作用域方式解释更加准确
        function showBiBao() {
            for (var i = 0; i < 5; i++) {
                setTimeout((function (i) {
                    return function timer() {
                        console.log(i);}
                    })(i),1000);
            }
            console.log(i)
        }
        showBiBao()

        // var count = 0;
        // function add(){
        //     count = count + 1;
        //     console.log(count);
        // }
        // add(); // 确实实现了需求
        // // 但是如果需要第二个计数器呢
        // // 难道要如下这样写吗
        // var count1 = 0;

        // function add1(){
        //     count1 = count1 +1;
        //     console.log(count1);
        // }
        // add1(); // 确实实现了需求

        // function addCount(){
        //     var count = 0;
        //     return function(){
        //         count = count + 1
        //         console.log(count);
        //     }
        // }

        // var fun1 = addCount()
        // fun1();
        // fun1();
        // var fun2 = addCount();
        // fun2();
        // fun2();

        // for (var i = 0; i < 4; i++) {
        //     setTimeout(function () {
        //         console.log(i)
        //     }, 300);
        // }

        // for (var i = 0; i < 4; i++) {
        //     setTimeout(
        //         (function (i) {
        //             return function () {
        //                 console.log(i);
        //             };
        //         })(i), 300
        //     )
        // }

        // for(var i = 0; i < 4; i++){
        //     (function(i){
        //         setTimeout(function(){
        //             console.log(i)
        //         },300)
        //     })(i)
        // }

#函数递归

        // 递归函数 就是函数内部调用自己
        // 这个函数就是递归
        var count = 0;
        function fn() {
            count++;
            if(count >= 20){
                return
            }
            fn()
        }
        fn();
        console.log(count)

#求n的阶乘

        function fn(num){
            if(num == 1){
                return 1
            }
            return num * fn(num - 1)
        }
        console.log(fn(5))

#数组的深度遍历

        // 多维数组
        var arr = [1,2,3,[4,5,[6,7,8]]]
        // arr.forEach(function(item){
        //     console.log(item)
        // })
        function bianli(arr) {
            for(var i = 0; i < arr.length; i++){
                if(arr[i].length > 0){
                    bianli(arr[i])
                }else{
                    console.log(arr[i])
                }
            }
        }
        bianli(arr)

#浅拷贝

        var arr1 = [1,2,3,4]
        var arr2 = arr1; // 赋予的是一个地址
        arr2[0] = 100;
        console.log(arr1[0]) // 此处打印出100

#深度拷贝

        // 在js中对象和数组、函数存在于堆内存中
        // 字面量存在于栈中

        var arr1 = [1,2,3,4,5]
        // var arr2 = arr1
        var arr2 = []

        // 深度拷贝1
        for(var i = 0; i < arr1.length; i++){
            arr2.push(arr1[i])
        }
        arr2[0] = 100
        console.log(arr2)
        console.log(arr1)

        // 深度拷贝2
        var str = arr1.join(",")
        console.log(str)
        var arr3 = str.split(",")
        console.log(arr3)
        for(var i = 0; i < arr3.length; i++){
            arr3[i] = parseInt(arr3[i])
        }
        // arr3.forEach(function(item){
        //     arr3[item] = parseInt(arr3[item])
        // })
        console.log(arr3)

        // 深度拷贝3
        var arr4 = [1,2,3,4,5]
        // stringify:字符串化
        // var str = JSON.stringify(arr4) // 这是一个字符串
        // var arr5 = JSON.parse(str)
        // 可以连写这两个数组
        var arr5 = JSON.parse(JSON.stringify(arr4))
        arr5[0] = 100;
        console.log(arr5)
        console.log(arr4)