• 【学习笔记17】JavaScript作用域


    笔记首发

    一、作用域

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

    1、全局作用域

    1. 😫 script标签内部声明的变量,就是全局作用域的变量
    2. 😏在全局作用域声明的变量, 在哪里都可以使用
    3. 😣浏览器在运行的时候,会给我们一个window对象, 我们的全局作用域内声明的变量,全都在window对象中

    2、局部(函数)作用域

    1. 🤒 在函数内部的大括号内,这个区间叫做函数作用域
    2. 😴 在函数作用内声明的变量, 只能在当前函数内部使用, 在函数外部(超过作用域了) 就无法使用
    3. 😪 函数作用域内声明的变量, 不会挂载到window对象
           // 在全局作用域中声明的变量, 同时他也会挂载到全局对象window
            var a = 100;
            // 在全局作用域中声明的变量, 同时他也会挂载到全局对象 window
            var a1 = '这是我手写的';
    
            console.log(window)
    
            function fn() {
                // 这里边就是函数作用域
                var amyFn = '我是在函数作用域内声明的变量';
                 // 我是在函数作用域内声明的变量
                console.log(amyFn) 
            }
            fn()
            // amyFn is not a defined
            console.log(amyFn);   //报错  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    二、作用域链

    1、变量的访问规则

    1. 😴 会先在自己当前作用域内查找, 找到直接使用(打印)
    2. 😴 如果没有找到,会向上层作用域查找, 不会向下层查找
    3. 😴 如果上层作用域内也没有找到, 会继续向上层作用域的上层作用域查找(相当于是去自己爷爷级作用域)
    4. 😴 一直会找到最顶层的全局作用域, 找到就是用, 找不到报错
            var a = 100;
    
            function fn() {
                /**
                 *  会先在自己当前作用域(fn函数内部)查找, 找到直接使用, 这里找不到, 因为函数内部没有声明变量a
                 *  那么会去自己的上一层作用域(全局作用域)中查找, 找到直接使用
                */
                console.log(a)  // 100
    
                function fn1() {
                    var a = 200;
                    console.log(a);  //200
                }
                fn1()
            }
            fn()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

            var a = 1;
            function fn() {
                function fn1() {;
                    console.log(a)    // 1
                    /**
                     * 查找规则:
                     *      1. 在当前作用域(fn1函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(fn函数内部)
                     *      2. 在父级作用域(fn函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(全局)
                     *      3. 在全局作用域查找, 找到直接使用, 找到了var a = 1;    所以会打印1
                    */
                }
                fn1()
            }
            fn()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
            function fn() {
                function fn1() {
                    console.log(a)
                    /**
                     * 查找规则:
                     *      1. 在当前作用域(fn1函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(fn函数内部)
                     *      2. 在父级作用域(fn函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(全局)
                     *      3. 在全局作用域查找, 找到直接使用, 没找到    所以会报错
                    */
                }
                fn1()
            }
            fn()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、变量的赋值规则

    1. 🤒 会先在自己当前作用域内查找, 找到直接赋值
    2. 🤒 如果没找到, 会向上层作用域查找, 不会向下层查找
    3. 🤒 如果上层作用域内也没有找到, 会继续向上层作用域的上层作用域查找(去自己的爷爷级作用域)
    4. 🤒 一直会找到最顶层的全局作用域, 找到直接赋值, 找不到将变量定义为全局变量,并赋值
    
            function fn() {
    
                function fn1() {
                    a = 1
                    /**
                     * 赋值规则:
                     *      1. 在当前作用域(fn1函数内部)查找, 找到直接赋值, 但是没找到, 所以会去父级(fn函数内部)
                     *      2. 在父级作用域(fn函数内部)查找, 找到直接使用, 但是没找到, 所以会去父级(全局)
                     *      3. 在全局作用域查找, 找到直接赋值, 没找到; 所以会将变量定义为全局变量并赋值
                    */
                }
                fn1()
            }
            fn()
    
            console.log(a)  // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3、作用域链(纯概念)

    • 😦 在自己作用域内查找, 找不到去上层, 不会去下层, 这样一层一层的一个链条 我们叫做作用域链
    • 😑 简单总结: 永远向上查找, 不会向下

    三、递归函数

    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的阶乘  24
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2、课堂案例

        /**
         *  现在有一个特殊的数列,前两位的值是固定为1
         *  从第三位开始, 他的值为前两位相加的和
         * 
         *  1 1 2 3 5 8 13 21 34 55
         *  递归比较好用, 但是计算量大的时候慎用
        */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
            function fn(n) {
                if (n == 1 || n == 2) {
                    return 1;
                }
                /**
                 *  假设 我想求 第六位
                 * 
                 *  return 第五位 + 第四位
                 *  return fn(5) + fn(4)
                 *  return fn(n - 1) + fn(n - 2)
                */
                return fn(n - 1) + fn(n - 2);
            }
            var sum = fn(200);
            console.log(sum);  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    位逻辑运算符
    基于OpenFeign的服务调用
    【华为机试真题】字符串匹配
    <Linux进程控制>——《Linux》
    「Python实用秘技16」快速提取字体子集
    千万级订单生成的痛点与架构
    android adb读写权限单独控制
    【小专题】正交试验法设计测试用例
    CANopen DS402名词
    Scala / Java - Guava Sets 高效实践
  • 原文地址:https://blog.csdn.net/m0_58190023/article/details/128025280