js 执行环境、作用域链和闭包

执行环境:

定义了变量或函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中(如同全局环境下的变量和函数保存在window对象内)

执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出,例如关闭网页或浏览器时才会被销毁)

只有函数有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中, 而在函数执行之后,栈将其环境弹出(当环境被弹出后,会对其中的变量和函数进行标记,在下一次GC运行时进行回收,存在闭包时除外),把控制权返回给之前的执行环境

作用域链:

当代码在一个环境中执行时,会创建变量对象的一个作用域链;用途是保证对执行环境有权访问的所有变量和函数的有序访问

作用域链的前端,始终都是当前执行的代码所在环境的变量对象,执行环境中的变量对象是当前函数的活动对象(函数的活动对象默认只有一个arguments变量,此外还包含函数的实参和函数内定义的变量及函数);

作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境,这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象

作用域链前端可延长(with:将指定的变量对象添加到前端;try-catch的catch块:创建一个新的变量对象并添加到前端,其中包含的是被抛出的错误对象的声明)

js的作用域属于 词法作用域(其描述了 JS 解析器如何处理嵌套函数中的变量,指一个变量在源码中声明的位置作为它的作用域,同时嵌套的函数可以访问到其外层作用域中声明的变量),注意不管当前词法作用域在父级作用域的什么位置,都可以访问到父级作用域内的所有变量和函数,如下例:

// 在read内部作用域中RHS查询无法得到word,从而往嵌套的父级作用域(全局作用域)查找,即使word在其下面定义,仍可访问得到
function read(){
  console.log(word)
}

var word = 'hello'

闭包:

闭包是函数和声明该函数的词法环境的组合

无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包,方式包括:返回内部函数、外部变量在内部设置为指向内部函数、返回携带内部函数引用的变量等等

根据词法作用域,内部作用域本应在函数执行完毕被回收,但由于外部持有对其的引用,即闭包,需要保证被引用的内部函数在任何时候均能访问到内部作用域,内部作用域就没有被回收,可以理解为‘闭包扩展了词法作用域’

欢迎关注、点赞

猜你喜欢

转载自blog.csdn.net/qq_33576343/article/details/84792316
今日推荐