你真的理解作用域以及递归循环吗

73 阅读3分钟

01-作用域

以局部变量为荣,以全局变量为耻

作用域分为

  1. 全局作用域--widow window是全局作用域
  2. 局部作用域

在JS中,有 且只有 函数能创建局部作用域(函数作用域),局部作用域开始和结束位置,就是函数代码段的开始和结束位置,在函数作用域中,声明的变量称为局部变量--局部变量不会挂载到 window 对象上

var num = 100 //李四
function fn(){
    var num =1000  //张三
    console.log(num)
}
console.log(num)  //李四

在开发中,尽可能的使用局部变量;要避开起名的时候使用name

02-作用域链

什么是作用域链?

在查找变量时,会先在当前作用域内查找,找到就用,没找到会向上查找(父级),一直到顶层作用域(全局--window)

在我们一层一层查找所构成的链条,就叫做作用域链----但是作用域链只会向上级查找,不会向下查找

变量的访问规则

变量访问会现在当前作用域内查找,找到直接用,没找到会去上层作用域查找,直到全局作用域,如果全局作用域内还是没有变量,那么就会报错--xx is not defined

变量的赋值规则

变量赋值会现在当前作用域内查找,找到直接拿来赋值,没找到会去上层作用域查找,直到全局作用域内,还是没有找到变量,那么会直接将变量定义在当前作用域内(全局作用域)然后赋值

        // function fn() {
        //     function fn1() {
        //         num = 1000;
        //     }
        //     fn1()
        // }
        // fn()
        // console.log(num)
        /**
         * 首先 在 fn1 这个作用域内 给变量 num 赋值
         *      那么 会先在当前作用域(fn1)查找 num,  但是没找到, 所以会去上层作用域内查找(fn)
         *      在 fn 作用域内查找后, 发现还是没有, 去继续去上层作用域内查找(全局---window)
         *      然后发现, 在全局作用域内 仍没有找到一个叫做 num 的变量
         *      那么会直接将 num 定义在全局, 然后赋值
        */
        function fn() {
            var num = 10000
        }
        fn()
​
        console.log(num)    // 'num' is not a defined
        /**
         * 在此处打印变量 num
         *      会先在当前作用域内查找, 找到就使用, 找不到去上层, 但! 此时已经是全局作用域, 所以不会去上层, 找不到直接报错
         * 
         *      同时注意: 不会向下 查找
        */

03-递归循环

想要写一个正确的递归函数,需要在递归内部写上返回点(到某一个条件时,停止递归)

        function fn(n) {
            // 1. 先写折返点, 到某个条件停止递归
            if (n == 1) return 1
​
            // 2. 不符合结束递归时的代码
            return n * fn(n - 1)
        }

案例--某个数的阶乘--一个数的阶乘等于他本身乘他自身减一的阶乘

function fn(n){
    if (n == 1) return 1 //当if函数只有一个运行条件,可以省略大括号
    return n * fn(n - 1)
}
var num = fn(4) //计算4的阶乘
consolelog(sum)
​
​
        /**
         * fn(4)
         *      运行 if 判断 n == 1 吗, 不等于, 所以运行 --> 4 * fn(3)  ---> 根据下一轮的执行, 知道 fn(3) == 6 所以此处运算为 24
         *      
         *          fn(3)   ---> 6
         *              运行 if 判断 n == 1 吗, 不等于, 所以运行 --> 3 * fn(2)  ---> 根据下一轮的执行, 知道 fn(2) == 2 所以此处运算为 6
         *          
         *                  fn(2)   --> 2
         *                  运行 if 判断 n == 1吗, 不等于, 所以运行 --> 2 * fn(1)   ---> 根据下一轮的执行, 知道 fn(1) == 1 所以此处运算为 2
         * 
         *                      fn(1)  --> 1
         *                      运行 if 判断 n == 1吗, 条件符合, 直接返回1, (递归  递的阶段结束, 开始归的阶段)
        */

案例二--斐波那契数列

1 1 2 3 5 8 13 21 24

funtion fun(n){
    if (n == 1) || (n == 2){
        return 1  //fan'j
    }
    return fun(n-1) + fun(n-2)  //第n位的前一位 + 第n位的前两位
}
var sum = fun(10)
console.log(sum)

\