递归函数及什么是作用域

85 阅读4分钟

作用域

*我们的变量不是说 在任何地方都可以使用
 就是变量有一个使用区间, 这个可以使用的区间 就叫做 作用域

全局作用域 && 局部作用域

作用域分为两个
    1. 全局作用域
        就是再 script 标签内部声明的变量 就是全局作用域的变量
        在 全局作用域声明的变量, 在哪里都可以使用
        浏览器在运行的时候 会给我们一个 window 对象, 我们的全局作用域 内声明的变量 全都在 window 对象中
    2. 局部(函数)作用域
        就是在 函数内部 的大括号内 这个区间叫做 函数作用域
        在函数作用内声明的变量, 只能在当前函数内部使用, 在函数外部(超过作用域了) 就无法使用
        函数作用域内声明的变量, 不会挂载到 window 对象上

    
    var a = 100                 // 在全局作用域中声明的变量, 同时他也会挂载到全局对象 window
    var a1 = '全局变量'          // 在全局作用域中声明的变量, 同时他也会挂载到全局对象 window

    console.log(window)

    function fn() {
        // 这里边就是函数作用域
        var amyFn = '作用域内声明的变量'
        console.log(amyFn)      // 作用域内声明的变量
    }
    fn()

    console.log(amyFn)          // amyFn is not a defined

作用域链

变量的访问规则
    console.log(a)
    会先在自己当前作用域内查找 变量 a, 找到直接使用(打印)
    如果没有找到!!! 会向上层作用域查找, 不会向下层查找!!!
    如果 上层作用域 内也没有找到, 会继续向 上层作用域的上层作用域查找(相当于是去自己爷爷级作用域)
            
    一直会找到最顶层的全局作用域, 找到就是用, 找不到 就报错
        
变量的赋值规则
    a = 1
    会先在自己当前作用域内查找 变量a, 找到直接赋值
    如果没找到!!! 会向上层作用域查找, 不会向下层查找!!!
    如果上层作用域内也没有找到, 会继续向上层作用域的上层作用域查找(去自己的爷爷级作用域)
        
    一直会找到最顶层的全局作用域, 找到直接赋值, 找不到 将 变量定义为全局变量  并赋值
        
作用域链(纯概念)
    在自己作用域内查找, 找不到去上层, 不会去下层, 这样一层一层的一个链条 我们叫做作用域链
    简单总结: 永远向上查找, 不会向下

var a = 100

    // function fn() {
    //     /**
    //      *  会先在自己当前作用域(fn函数内部) 查找, 找到直接使用, 这里找不到, 因为函数内部没有声明变量a
    //      *  那么会去自己的上一层作用域(全局作用域)中查找, 找到直接使用
    //     */
    //     console.log(a)  // 100

    //     function fn1() {
    //         var a = 200
    //     }
    // }
    // fn()

    // var a = 1
    // function fn() {

    //     function fn1() {
    //         console.log(a)   // 1
    //         /**
    //          * 查找规则:
    //          *      1. 在当前作用域(fn1函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(fn函数内部)
    //          *      2. 在父级作用域(fn函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(全局)
    //          *      3. 在全局作用域查找, 找到直接使用, 找到了 var a = 1;    所以会打印1
    //         */
    //     }
    //     fn1()
    // }
    // fn()

    // function fn() {

    //     function fn1() {
    //         console.log(a)
    //     }
    //     fn1()
    // }
    // fn()


    function fn() {

        function fn1() {
            a = 1
            /**
             * 赋值规则:
             *      1. 在当前作用域(fn1函数内部)查找, 找到直接赋值, 但是没找到, 所以会去父级(fn函数内部)
             *      2. 在父级作用域(fn函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(全局)
             *      3. 在全局作用域查找, 找到直接赋值, 没找到    所以会将变量定义为全局变量 并赋值
            */
        }
        fn1()
    }
    fn()
    console.log(a)  // 1

递归函数

递归函数
    条件1   一个函数 在内部 调用了 自身
    条件2   在合适的实际 结束调用(结束递归) 一定要有, 不然就是 死递归

写一个简单的递归

function fn(n) {
        if (n == 1) {
            return 1
        }
            // return 4 的阶乘
            // return 4 * 3 的阶乘
            // return 4 * fn(3)
        return n * fn(n - 1)
    }
    var sum = fn(4)
    console.log(sum)    // sum 就是 4 的阶乘