• 作用域与闭包


    一、变量提升

    变量和函数在内的所有声明都会在任何代码被执行前首先被处理。

    举个例子:

    当你看到 var a = 2; 时,可能会认为这是一个声明,但实际上 Javascript 会将其看成两个声明:var a ; 和 a = 2;并且在不同阶段执行。var a 是在编译阶段进行的,而 a = 2 会被留在原地等待执行阶段。

    这个过程就好像变量和函数声明从它们在代码中出现的位置被“移动”到了最上面,这个过程就叫做变量提升。

    foo();
    
    function foo(){
        console.log(a);
        var a = 2;
    }

    foo()可以正常执行,控制台打印出undefined。这段代码相当于下面这种形式:

    function foo() {
        var a;
        console.log(a);
        a = 2; 
    }
    
    foo();

    重点:

    1.对于函数,函数声明会被提升,而函数表达式不会被提升。

    foo(); //TypeError
    
    var foo = function(){
        console.log(a);
        var a = 2;
    }

    2、重复声明后面的会覆盖前面的。

    foo(); // 3
    
    function foo(){
        console.log(1);
    }
    var foo = function(){
        console.log(2)
    }
    
    function foo(){
        console.log(3)
    }

     二、闭包

    当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

    function foo(){
        var a = 2;
        function bar(){
            console.log(a);
        }
        return bar;
    }
    
    var baz = foo();
    baz(); //2

    这里通过调用 baz 来调用 foo 内部的 bar , bar 在自己定义的词法作用域以外的地方执行,在 foo 执行之后,通常会期待 foo 的整个内部作用域被销毁,因为引擎的垃圾回收器会释放不再使用的内存空间。看上去 foo 不再被使用,所以很自然的考虑到对其进行回收,然而闭包就是阻止这样的事情发生,事实上内部作用域依然存在,没有被回收,因为 bar 依然在使用该作用域。

    bar 拥有 涵盖 foo 内部作用域的闭包,使得该作用域能够一直存活,以供 bar 在之后任何时间进行引用。

    bar 依然持有对该作用域的引用,而这个引用就叫作 闭包。

    bar 在定义时的词法作用域以外的地方被调用,闭包使得函数可以继续访问定义时的作用域。

  • 相关阅读:
    编码的道与禅
    使用 C# 编写简易 ASP.NET Web 服务器
    程序员的职业素养
    NServiceBus官方文档翻译(二)NServiceBus 入门
    NServiceBus官方文档翻译(一)NServiceBus 概况
    七周七语言之使用prolog解决爱因斯坦斑马难题
    七周七语言之用Io编写领域特定语言
    七周七语言之用ruby做点什么
    利用binarySearch实现抽奖计算逻辑
    Java设计模式三
  • 原文地址:https://www.cnblogs.com/PeriHe/p/8539054.html
Copyright © 2020-2023  润新知