JavaScript-作用域、块级作用域、上下文、执行上下文、作用域链

2018-05-17 阅读 1765 收藏 3

一、作用域

在 JavaScript 中, 作用域(scope,或译有效范围)就是变量和函数的可访问范围,即作用域控制着变量和函数的可见性生命周期

二、全局/局部作用域

2.1 全局作用域(Global Scope)

(1)不在任何函数内定义的变量就具有全局作用域。

(2)实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性

全局作用域

(3)window对象的内置属性都拥有全局作用域,例如 window.name、window.location、window.top 等。

2.2 局部作用域(Local Scope)

(1)JavaScript的作用域是通过函数来定义的,在一个函数中定义的变量只对这个函数内部可见,称为函数(局部)作用域

三、全局/局部变量

变量能够被定义在局部或者全局作用域,这导致运行时变量的访问来自不同的作用域

3.1 全局变量

(1)在函数定义外声明的变量是全局变量。

(2)全局变量有 全局作用域,它的值可在整个程序中访问和修改

(3)如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。

3.2 局部变量

(1)在函数定义内声明的变量是局部变量。

(2)因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量

(3)每当执行函数时,都会创建销毁该变量,且无法通过函数之外的任何代码访问该变量。

(4)函数外无法访问函数内的变量,函数内却可以访问函数外的变量。

四、全局变量

1、在函数定义外声明的变量是全局变量;全局变量有全局作用域,它的值可在整个程序中访问和修改

全局变量

2、如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。

全局变量

五、局部变量

1、因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量

局部变量

2、每当执行函数时,都会创建销毁该变量,且无法通过函数之外的任何代码访问该变量。

局部变量

3、函数外无法访问函数内的变量,函数内却可以访问函数外的变量。

局部变量

六、块级作用域

6.1 概念

块级作用域指在If语句,switch语句,循环语句等语句块中定义变量,这意味着变量不能在语句块之外被访问

6.2 var 不支持块级作用域

(1)在If等语句块中,定义的变量从属于该块所在的作用域,和函数不同,他们不会创建新的作用域。

var

6.3 let和const

(1)为了解决块级作用域,ES6引入了 letconst 关键字,可以声明一个块级作用域的变量

let和const

(2)全局作用域的生存周期与上述应用相同。局部作用域只在该函数调用执行期间存在。

七、上下文 vs 作用域

(1)首先需要说明的是上下文和作用域是不同的概念

(2)每个函数调用都有与之相关的作用域和上下文。从根本上说,作用域是基于函数,而上下文是基于对象

(3)作用域是和每次函数调用时变量的访问有关,并且每次调用都是独立的。上下文总是关键字 this 的值,是调用当前可执行代码的对象的引用。

八、“this” 上下文

(1)上下文通常是取决于一个函数如何被调用。当函数作为对象的方法被调用时,this 指向调用方法的对象

上下文

(2)当调用一个函数时,通过 new 操作符创建一个对象的实例,当以这种方式调用时,this 指向新创建的实例

上下文

(3)当调用一个未绑定函数,this 默认指向全局上下文或者浏览器中的window对象。然而如果函数在严格模式下被执行(“use strict”),this 默认指向 undefined

九、执行上下文

(1)当函数执行时,会创建一个称为执行上下文的内部对象(可理解为作用域,不是前面讨论的上下文)。一个执行上下文定义了一个函数执行时的环境

(2)函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文。

(3)当javascript代码文件被浏览器载入后,默认最先进入的是一个全局的执行上下文。当在全局上下文中调用执行一个函数时,程序流就进入该被调用函数内,此时引擎就会为该函数创建一个新的执行上下文,并且将其压入到执行栈顶部(作用域链)。浏览器总是执行位于执行栈顶部的当前执行上下文,一旦执行完毕,该执行上下文就会从执行栈顶部弹出,并且控制权将进入其下的执行上下文。这样,执行栈中的执行上下文就会被依次执行并且弹出,直到回到全局的执行上下文。

十、作用域链

(1)在JavaScript中,函数也是对象,对象中有些属性我们可以访问,但有些不可以(访问),这些属性仅供JavaScript引擎存取,**[[scope]]**就是其中一个。

(2)[[scope]]指的就是我们所说的作用域,其中存储了执行上下文的集合。

(3)[[scope]]中所存储的执行上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

10.1 示例

执行期上下文

(1)运行示例代码将会导致嵌套的函数被从上倒下执行,一直到 fourth 函数,此时作用域链从上到下为: fourth, third, second, first, global。

(2)fourth 函数能够访问全局变量和任何定义在first,second和third函数中的变量(和访问自己的变量一样)。

(3)一旦fourth函数执行完成,其就会从作用域链顶部移除,并且执行权会返回到third函数。这个过程一直持续到所有代码完成执行。

10.2 攀爬作用域链

(1)当不同执行上下文之间存在 变量命名冲突,可以通过攀爬作用域链解决(从顶部到底部)。这也就是说 在最内层函数(执行栈顶部的执行上下文)中,具有相同变量名称的变量将具有较高优先级。

(2)简单的说,每次试图访问函数执行上下文中的变量时,查找进程总是从自己的变量对象开始。如果在自己的变量对象中没发现要查找的变量,继续搜索作用域链。他将攀爬作用域链检查每一个执行上下文的变量对象,去寻找和变量名称匹配的值

阅读更多

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/dev…

回到顶部