变量作用域


变量的作用域指的是程序源码中定义这个变量的区域,全局变量具有全局作用域,可以在 JavaScript 代码中任意位置使用,而在函数内声明的变量只能在函数内使用,属于局部变量,函数参数也是局部变量,只在函数体内有定义。

需要注意的几点:

  • 在函数体内局部变量的优先级高于全局变量,如果存在变量同名问题,局部变量会覆盖全局变量;
  • 全局变量声明时可以不使用 var 语句,但是局部变量声明时必须使用;
  • 函数定义可以嵌套,这个时候要格外注意局部变量的作用域。

函数作用域

函数作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是可用的,甚至在变量声明之前就可以使用,JavaScript 的这一特性被非正式的称为声明提前。

函数作用域

在执行第一条 console.log 语句时,局部变量已经覆盖了全局变量,但是还没有走到赋值语句那里,所有打印的是 undefined,赋值之后才打印出 local。由此可见,在函数体内的所有变量声明都是提前到了函数体顶部,而初始化则是在声明处。

作为属性的变量

当声明一个 JavaScript 全局变量时,实际上定义了全局对象的一个属性(ECMAScript 规范规定),当使用 var 声明一个变量时,创建的这个属性是不可配置的(不可以通过 delete 运算符删除),如果没有通过 var 声明的全局变量则是正常的可配置的属性:

作为属性的变量

局部变量也可以理解为跟函数调用相关的某个对象的属性,但是却不能通过类似全局变量那样通过 this 进行引用,这种存放局部变量的特有性质是一种对我们不可见的内部实现。

作用域链

如果将局部变量看作是自定义实现的对象的属性的话,那么可以换个角度来解读变量作用域,每段 JavaScript 代码都有一个与之关联的作用域链,这个作用域链是一个对象列表或链表,对象中定义了作用域中的变量。

在 JavaScript 最顶层代码中,作用域链由一个全局对象组成;在不包含嵌套的函数体中,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象;在一个嵌套的函数体内,作用域链上至少有三个对象,每次调用外部函数时,内部函数需要重新定义一遍,因为每次调用外部函数时,作用域链可能都是不同的。

当 JavaScript 需要做变量解析时(比如查找变量 x),它会从链中的第一个对象开始查找,如果链中有一个名为 x 的属性,则直接使用这个属性值;如果不存在的话则会查找链上的下一个对象,依次类推,如果链上所有对象都没有包含属性 x,则认为属性 x 不存在,抛出一个引用错误异常。

作用域的概念对于理解 with 语句和闭包的概念都很有帮助。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 变量声明

>> 下一篇: 表达式概述