一、作用域
在 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、函数外无法访问函数内的变量,函数内却可以访问函数外的变量。(闭包)
块级作用域
块级作用域指在If语句,switch语句,循环语句等语句块中定义变量,这意味着变量不能在语句块之外被访问。
4 var 不支持块级作用域
(1)在If等语句块中,定义的变量从属于该块所在的作用域,和函数不同,他们不会创建新的作用域。
let和const
(1)为了解决块级作用域,ES6引入了 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]]中所存储的执行上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
(1)运行示例代码将会导致嵌套的函数被从上倒下执行,一直到 fourth 函数,此时作用域链从上到下为: fourth, third, second, first, global。
(2)fourth 函数能够访问全局变量和任何定义在first,second和third函数中的变量(和访问自己的变量一样)。
(3)一旦fourth函数执行完成,其就会从作用域链顶部移除,并且执行权会返回到third函数。这个过程一直持续到所有代码完成执行。