zoukankan      html  css  js  c++  java
  • [JavaScript]JavaScript中的函数(2)

    承接上一篇博文的总结,这篇博文是利用代码+画图的形式,梳理一下对于函数作用域和闭包的理解。

    函数中的作用域

    在 JavaScript 中, 对象和函数同样也是变量。
    在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。

    首先我们声明一个函数,然后在函数内部声明并赋值一个变量:

    function fn(){
        var x = 3
        console.log(x)
    }
    fn.call()    //3
    

    在函数fn中就产生了一个作用域,要求打印x的值时,函数就会在自身内部寻找这个x,然后把结果打出来。

    在函数内部再次声明一个函数的话,情况会变成什么样呢:

    function fn(){
        var x = 3
        // console.log(x)
        function fn1(){
            var x = 4
            console.log(x)
        }
        fn1.call()
    }
    fn.call()   //4
    

    函数fn1在fn作用域内创造了一个子作用域,打印的时候不使用fn中的变量x,而是使用了这个子作用域内的变量x。

    如果fn1中没有声明变量x,他会打印出什么呢?

    function fn(){
        var x = 3
        function fn1(){
            console.log(x)
        }
        fn1.call()
    }
    fn.call()   //3
    

    子作用域

    他会去寻找fn中的x,然后把他打印出来。

    如果函数fn作用域内也不存在这个变量呢?

    var x = 5
    function fn(){
        function fn1(){
            console.log(x)
        }
        fn1.call()
    }
    fn.call()   //5
    

    全局作用域

    由此可以看出:在调用函数作用域(fn1)中的某个变量(x)时,他会先在自身作用域中寻找这个变量;如果这个变量没有找到,那么这个函数可以访问上一级作用域(fn)中的变量(x);如果这个变量还没有找到,那么这个函数可以访问更上一级,即全局作用域(window)中的x。

    注意

    在理解作用域的同时,我们要十分注意变量提升的问题。

    比如:

    function fn(){
        function fn1(){
            console.log(x)
            var x = 5
        }
        fn1.call()
    }
    fn.call()   //undefined
    

    为什么会打印出了undefined呢?

    因为这段代码实际上表达的意思是这样:

    function fn(){
        function fn1(){
            var x
            console.log(x)
            x = 5
        }
        fn1.call()
    }
    fn.call()   //undefined
    

    变量x只是做出了声明,但是并没有赋值,所以打印出来是undefined。

    闭包

    既然理解了函数作用域,就能理解闭包了。

    「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。

    比如上文这张图:

    函数fn1加上他可以访问的位于函数fn的作用域内的变量x,就是一个闭包。

    关于闭包的更详细的解释,可以看看方应杭方老师的这篇文章,我们充分理解,学以致用,就可以了。

    关于作用域的面试题

    var x = 5
    function fn(){
    	x = 2
    	console.log(x)
    }
    fn.call()   //2
    

    fn先在自身作用域内寻找变量x,但是这个x是只赋值没有声明,然后到全局作用域去找,发现了一个声明并且赋值了的变量x,然后就把这个变量重新赋值,覆盖了原来的值,输出结果。

    注意:这里涉及到了赋值与声明的问题,声明是声明,赋值是赋值,声明和赋值不一样。
    var x = 5 是声明了一个全局变量x,然后把5赋值给了x
    x = 2 是把2赋值给了一个变量x,但是并没有声明;如果全局变量中没有声明x,那么这个时候才可以认为这个x被声明并且被赋值了

  • 相关阅读:
    Vue3手册译稿
    Vue3手册译稿
    Vue3手册译稿
    Vue3手册译稿
    Vue3手册译稿
    Vue3手册译稿
    C# 多线程与异步的使用方法笔记
    PetaPoco 5.1.306 的生成模板加注释
    RichEditDocumentServer打印记录
    RichEditDocumentServer 打印份数
  • 原文地址:https://www.cnblogs.com/No-harm/p/9542324.html
Copyright © 2011-2022 走看看