JavaScript作用域、作用域链

作用域

变量或函数可以发生作用的区域即是作用域。

作用域的最大用途就是隔离变量或函数,并控制变量或函数的生命周期,超过该区域的变量或函数就不能被访问。

js变量(不包括函数)的作用域是函数级的,也就是说定义变量的整个函数区域都可以访问到它,即使这个变量是否定义在while、if代码块中也可以。就像我们上面的例子,j是定义在代码块中的,然而在代码块外也可以访问到。


JavaScript作用域、作用域链_第1张图片

全局作用域

1、在最外层定义的变量和函数拥有全局作用域。

2、未声明直接赋值的变量拥有全局作用域。

3、在浏览器中,定义在window对象上的属性和方法,拥有全局作用域。

函数作用域

在某个函数内部声明的变量或函数拥有函数作用域。它们只能被该函数的语句使用,函数外部是不可访问的。函数在创建的时候,变量和函数的函数作用域已经确定下来。函数的参数也属于函数内部的变量,因此拥有函数作用域。

例子:



JavaScript作用域、作用域链_第2张图片
JavaScript作用域、作用域链_第3张图片

第一段代码是在函数中找到a变量,第二段代码是在全局中找到b变量。现在闭上眼睛,我要给加粗的这两个词的后面加上几个字了!

好了,打开眼睛,Duang,Duang --->函数作用域全局作用域,把这两个词换入到原来那句话中,第一段代码是在函数作用域中找到a变量,第二段代码是在全局作用域中找到b变量。

我们在查找b变量的时候,先在函数作用域中查找,没有找到,再去全局作用域中查找,有一个往外层查找的过程。我们好像是顺着一条链条从下往上查找变量,这条链条,我们就称之为作用域链


JavaScript作用域、作用域链_第4张图片

查找变量也是顺着红色的箭头走的,从里到外,这从里到外的各层作用域就组成了作用域链。

词法作用域:函数的作用域在函数定义的时候就决定了。与词法作用域相对的是动态作用域。

动态作用域:函数的作用域是在函数调用的时候才决定的。


JavaScript作用域、作用域链_第5张图片

执行上下文.变量对象(Variable Object)

1、确定 this 的值,也被称为 This Binding

2、LexicalEnvironment(词法环境) 组件被创建。用于存储函数声明和变量( let 和 const )绑定

3、VariableEnvironment(变量环境) 组件被创建。仅用于存储变量( var )绑定

词法环境有两个组成部分

1、环境记录:存储变量和函数声明的实际位置

2、对外部环境的引用:可以访问其外部词法环境


JavaScript作用域、作用域链_第6张图片

变量环境

变量环境也是一个词法环境

JavaScript作用域、作用域链_第7张图片


JavaScript作用域、作用域链_第8张图片

变量提升的原因:在创建阶段,函数声明存储在环境中,而变量会被设置为undefined(在 var 的情况下)或保持未初始化(在 let 和const 的情况下)。所以这就是为什么可以在声明之前访问 var 定义的变量(尽管是 undefined ),但如果在声明之前访问 let 和 const定义的变量就会提示引用错误的原因。这就是所谓的变量提升。

你可能感兴趣的:(JavaScript作用域、作用域链)