一、作用域
    定义:
    作用域[[scope]]: 每个js函数都有一个对象,对象中有些属性我们可以访问,有些不可以,这些属性仅供js引擎存取,[[scope]]就是其中一个,[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合,即作用域决定了代码区域块中变量和其他资源的可见性。
    域类型:

    1. 全局作用域:贯穿js文档,所用地方可访问;
    2. 局部作用域:
    • 函数作用域:函数内形成AO对象,外部无法访问;
    • 块级作用域(无,es6有该概念)

    二、作用域链
    定义:
    作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
    执行期上下文定义:
    当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,执行上下文被销毁。
    三、举例
    列举下边的例子来说明作用域链:

    | function fn ( ) {
    function b ( ) {
    var b = 2;
    }
    var a = 1;
    b( );
    }

    fn( ); | | —- |

    fn在被创建时:会生成一个[[scope]]属性,这个属性有一个集合GO,被存储在[[scope]]域中的顶端,假设地址为0。如下图:
    js 作用域、作用域链 - 图1
    fn在被执行的时候,fn会预编译,创建一个AO对象(执行期上下文)被存储在fn[[scope]]域的最顶端,假设地址为0,这时GO对象的地址为1,如下图:
    js 作用域、作用域链 - 图2

    执行fn时,创建了函数b( ),b在创建时,生成[[scopw]],直接‘拿’fn的环境(域)当做自己的域:如下图:
    js 作用域、作用域链 - 图3
    执行b()时,b会创建自己AO对象,存储在域中的最顶端。如下图:
    js 作用域、作用域链 - 图4

    画的有点磕碜,见谅~
    b函数执行完会和自己执行时生成的AO分手,砍掉该作用域链,回到b创建时的‘样子’,这是b的scope-chain中剩下两条链a函数的AO和GO。
    a函数执行完时会和自己执行时产生的AO分手,砍掉该作用域链,回到a创建时的’样子’,这是a的scope-chain中剩下GO

    而变量的访问是按照作用域链自顶而下开始查找的,so,let’s go~
    function a () {
    function b () {
    x = 0;
    }
    var x = 1;
    b();
    console.log(x) // 0
    }

    如有不对,欢迎指正