• JavaScript中作用域问题讨论及示例代码探究


    作用域

    • 作用域指的是一个变量的可见区域
    • 作用域有两种:
      • 全局作用域
        • 全局作用域在网页运行时创建,在网页关闭时销毁
        • 所有直接编写到script标签中的代码都位于全局作用域中
        • 全局作用域中的变量是全局变量,可以在任意位置访问
      • 局部作用域
        • 块作用域
          • 块作用域是一种局部作用域
          • 块作用域在代码块执行时创建,代码块执行完毕它就销毁
          • 在块作用域中声明的变量是局部变量,只能在块内部访问,外部无法访问

    1 函数作用域

    • 函数作用域也是一种局部作用域
    • 函数作用域在函数调用时产生,调用结束后销毁
    • 函数每次调用都会产生一个全新的函数作用域
    • 在函数中定义的变量是局部变量,只能在函数内部访问,外部无法访问
    function fn(){
        let a = "fn中的变量a"
        console.log(a)
    }
    
    fn()
    console.log(a) // undefined 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2 作用域链

    当我们使用一个变量时,JS解释器会优先在当前作用域中寻找变量,就近原则

    • 如果找到了则直接使用
    • 如果没找到,则去上一层作用域中寻找,找到了则使用
    • 如果没找到,则继续去上一层寻找,以此类推
    • 如果一直到全局作用域都没找到,则报错 xxx is not defined

    参照下面的例子理解

    报错的原因看下一节提升相关概念

    let a = 10
    
    {
        console.log(a) // 报错,Cannot access 'a' before initialization
        let a = "第一代码块中的a"
        console.log(a) // "第一代码块中的a"
        {
            console.log(a) // 报错,Cannot access 'a' before initialization
            let a = "第二代码块中的a"
            console.log(a) // "第二代码块中的a"
        }
        console.log(a) // "第一代码块中的a"
    }
    console.log(a) // 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    let b = 33
    
    function fn() {
        console.log(b) // 报错,Cannot access 'b' before initialization
        let b = 44
        console.log(b) // 44
        function f1() {
            console.log(b) // 报错,Cannot access 'b' before initialization
            let b = 55
            console.log(b) // 55
        }
        f1()
    }
    
    fn()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3 练习

    练习1

    var a = 1
    
    function fn() {
        a = 2
        console.log(a) // 2
    }
    
    fn()
    console.log(a) // 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    练习2

    var a = 1
    
    function fn() {
        console.log(a) //undefined
        var a = 2
        console.log(a) // 2
    }
    
    fn()
    console.log(a) // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    练习3

    var a = 1
    
    function fn(a) {
        console.log(a) //undefined
        a = 2 	// 修改的是形参
        console.log(a) // 2
    }
    
    fn()
    console.log(a) // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    练习4

    var a = 1
    
    function fn(a) {
        console.log(a) //10
        a = 2
        console.log(a) // 2
    }
    
    fn(10)
    console.log(a) // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    练习5

    var a = 1
    
    function fn(a) {
        console.log(a) //1
        a = 2
        console.log(a) // 2
    }
    
    fn(a)
    console.log(a) // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    练习6

    console.log(a)  // a指向的是第五行的函数,var只是声明,并不赋值,如果声明过不会重复赋值
    
    var a = 1
    console.log(a) // 1
    function a() {
        alert(2)
    }
    console.log(a) // 1
    var a = 3
    console.log(a) // 3
    var a = function () {
        alert(4)
    }
    console.log(a) // 打印11行函数
    var a	// 已经声明过了,根本不执行
    console.log(a) // 打印11行函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    Java-List<Map>的复制 深拷贝与浅拷贝
    基于stm32的秒表计时器设计系统Proteus仿真
    11-JVM中常用垃圾回收器分析与实践
    java毕业设计——基于java+JSP+J2EE的户籍管理系统设计与实现——户籍管理系统
    Linux系统下如何使用NiMotionUSBCAN转换器?
    信息论基础(Part2)
    感谢信 | 企企通赋能鲜丰水果搭建特色数字化供应链协同系统,领跑中国水果连锁品牌
    Prometheus Operator 通过additional 添加target
    go-bindata - embed结合嵌入静态文件打包可执行二进制文件
    【软件测试从0到1】第三篇:用例篇
  • 原文地址:https://blog.csdn.net/qq_46311811/article/details/128137468