作用域
执行环境:简称环境,定义了变量或函数有权访问的其他数据,决定了它们各自的行为。
变量对象:每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。这个对象无法通过代码访问,但解析器在处理数据时会使用。
环境栈:每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就回被推入一个环境栈中,当这个函数执行后,栈将其环境弹出。把控制权返回给之前的执行环境。
作用域链:当代码在环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。
作用域链中的下一个变量对象来自包含环境,而再下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境,全局执行环境的变量对象始终都是作用域链中的最后一个对象
标识符解析:标识符解析是沿着作用域链一级一级地搜索标识符过程。搜索过程始终从作用域链的前端开始,逐级向后回溯,直至找到标识符。(找不到会报错)
延长作用域
:虽执行环境的类型总共有两种--全局和局部,但可以通过其他办法来延长作用域。因为有些语句可以在作用域链前端临时增加一个变量对象,改变量对象会在代码执行后被移除。
try-catch 语句的catch块
with 语句
这两个语句都会在作用域链的前端添加一个变量对象。对With语句来说,会将指定的对象天剑到作用域链中。对Catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
JS 中没有块级作用域
JavaScript 作用域不是以花括号包围的块级作用域,JS 中的变量作用域是有函数来决定的。
em:
注意:在JS中可以初始化未声明的变量。同时初始化未声明的变量会将该变量添加全局变量中。
JS 函数作用域
JavaScript 的函数定义是可以嵌套的,每一层是一个作用域,变量搜索是从内到外。
上述代码不会输出global,输出undefined。这是JavaScript的一个特性,按照作用域搜索顺序。在console.log函数访问Scope变量时,javaScript会先搜索函数f 的作用域,恰巧在f作用域里面搜索到scope变量,所有上层作用域中定义的Scope就被屏蔽了。但执行到console.log 语句时,scope还没被定义所以得到的就是undefined。
JS 的作用域是静态作用域
函数作用域的嵌套关系是定义时决定的,而不是调用时决定的,又叫词法作用域。这是因为作用域的嵌套关系可以在语法分析时确定,而不必等到运行时确定
输出 top top 说明了作用域的嵌套关系不是在调用时确定的,而是在定义时确定的