JavaScript作用域和作用域链

68 阅读1分钟

作用域

作用的区域或者说作用的范围

在全局作用域下写的变量:没有区别,全部属于window对象的属性

<script>
    var str1 = '123' // 全局变量 全局作用域 
    window.str2 = 123
    str3 = 123
    console.log(str1) // 123
    console.log(str2) // 123
    console.log(str3) // 123
</script>

在局部作用域写变量只能在局部访问,外部访问不到

<script>
function fn() {
    // 局部作用域
    var str1 = "123"
    console.log("str1") // 123
}
fn();
console.log(str1) // str1 is not defined
</script>

作用域链

从内部向外链,从当前作用域开始找,如果找不到向外作用域逐级查找

image.png

var str1 = "123" // 全局作用域
function fun1() {
    // var str1 = "abc"
    console.log(str1) // abc
}
fun1()

function fun2() {
    var str1 = "abc"
    console.log(str1) // abc
}
fun2()

面试题

<script>
    var str = "456"
    function fun () {
        var str = "123"
        console.log(str) // 123
    }
    fun()
    
    
    var str = "456"
    function fun () {
        // var str = "123"
        console.log(str) // 456
    }
    fun()
    
    
    var str = "456"
    function fun () {
        // var str; 这里会变量提升
        console.log(str) // undefined
        // var str = "123"
    }
    fun()
</script>
<script>
    var str = "123"
    function fun () {
        console.log(str) // 123
    }
    fun()
    
    
    function fun () {
        window.str = "123"
        console.log(str) // 123
    }
    fun()
    
    
    function fun () {
        console.log(str) // str is not defined
        window.str = "123" // 当前行不属于fun作用域的,他无法提升
    }
    fun()
</script>
<script>
    function fun () {
        console.log(str) 
        var str = "123" // 局部变量,会变量提升
    }
    fun()
    
    
    //  优先级: 参数 > 变量提升
    function fun (str) {
        console.log(str) // 456
        var str = "123" // 局部变量,会变量提升
    }
    fun("456")
    
    
    //  优先级: 函数 > 参数 > 变量提升
    function fun (str) {
        console.log(str) // function str
        var str = "123" // 局部变量,会变量提升
        function str() {
            return "abc"
        }
    }
    fun("456")
    
    
    //  优先级: 变量 > 函数 > 参数 > 变量提升
    function fun (str) {
        function str() {
            return "abc"
        }
        var str = "123" // 局部变量,会变量提升
        console.log(str) // 3
    }
    fun("456")
</script>

1.

var bar = 1
function test() {
    console.log(bar) // undefined
    var bar = 2;
    console.log(bar) // 2
}
test()

2.

var foo = function () {
    console.log(1)
}

function foo() {
    console.log(2) 
}
foo() // 1

3.

function f() {
    var b = 1
    function a() {
        console.log(b) // undefined
        var b = 2
        console.log(b) // 2
    }
    a()
    console.log(b) // 1
}
f()

4.

var name = "world"
(function(){
    if(typeof name === 'undefined') {
        var name = 'abc'
        console.log('goodbye:',name) // goodbye:abc
    } else {
        console.log('hello:',name)
    }
})()

5.

    var f = true
    if(f === true) {
        var a = 10
    }
    function fn() {
        var b = 20
        c = 30
    }
    fn()
    console.log(a) // 10
    console.log(b) // b is not defined
    console.log(c) // 30

记住这个顺序

  1. 作用域:从内部(当前作用域)逐级向上查找

  2. 顺序,优先级

    变量 > 函数 > 参数 > 变量提升