JavaScript作用域:全局作用域、局部作用域、块级作用域、作用域链、变量提升

1.作用域的概念

  • 通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。通俗的说,作用域:数据起作用的范围(某条数据可以在什么范围内使用)
  • js使用var声明变量,以function来划分作用域,大括号“{}” 却限定不了var的作用域。用var声明的变量具有变量提升(declaration hoisting)的效果。ES6里增加了let和count,可以在{}, if, for里声明。用法同var,但作用域限定在块级,let声明的变量不存在变量提升。

2.JS预解析机制(变量提升)

JS预解析机制(变量提升(Hoisting)):JS在读取到一个script标签(或者一个函数作用域)时,会先进行一个预解析的过程,在这个过程中,会把函数中的var声明的变量和function声明的函数体,提升到整个scriptt标签(或者一个函数作用域)最前边去。函数中var声明的变量会提升到函数内部的最前面,如果与外部的变量命名冲突,不会影响外部变量的声明以及赋值。函数内部使用一个变量时,首先会在函数内部寻找,如果没有,会一层一层向外查找。在预解析完之后,JS才会从上到下一行一行解析代码并执行。

  • var在预解析时,会把声明提升到最前边。只提升声明,不会把赋值过程进行提升(在赋值前打印会返回undefined)
  • function的函数体在预解析时,会把整个函数体提升至最前边
  • 函数表达式(函数表达式:var fn = function(){};)只会提升函数表达式的声明,不会执行(真正执行函数表达式前调用会返回undefined)
  • 在预解析时,会先预解析var(包括变量声明和函数表达式的变量声明),先把var放在最前面,然后再预解析function,所以当var和function重名时,function会覆盖var

 案例1:

      

   结果:

      

   案例2:

     

    结果:

    

注意:

JS预解析机制不是良好的编码习惯,不利于代码维护,建议不要使用,编码时建议先声明,再使用。

扩展:从概念的字面意义上说,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。

ES6之后就不能像JS预解析这么编写JS代码了,例如:

 

3.全局作用域

  • 通过var或function声明在全局(声明在任意函数之外和代码块之外)中的数据(在全局的任意地方都可以调用或修改),和在window下的属性
  • 最外层的全局作用域,任何地方都可以访问得到。在最外层作用域下使用 var 关键字会定义全局变量,也就是说会挂载在window 对象上,或者不使用关键字 var、let、const直接对变量名字进行赋值,JS也会自动为其创建为全局变量

      

4.局部作用域

  • 函数作用域:声明在函数内部的某个数据(var,function,参数),就只能在函数内部使用(函数的局部作用域)
  • 块级作用域(ES6新增)

       

  结果:

      

  注意:使用var声明在循环语句、条件判断语句即{}中的变量为全局变量

 

   结果为:

   

5.作用域链

当前的作用域内没有找到对应的变量就会向上去寻找 而这个过程构成的链式结构称为作用域链

  • 首先,JS引擎从当前的同一级开始查找变量。
  • 然后,如果找不到,引擎会在外层嵌套的作用域中继续查找。
  • 最后,直到找到该变量,或抵达最外层的全局作用域为止

案例1:

结果为:

案例2:

 结果为:

当函数中的变量与外部变量命名冲突时,这里把函数中var声明的a提升到函数中的最前面执行(相当于函数内部是一个全局作用域),但是赋值的操作不会提升,函数中使用变量a时会先在函数的作用域中找,前面三个打印找到了但未赋值所以是undefined。外面var声明的a不会受到函数的影响,所以还是10。

6.块级作用域

  • 块级作用域指在代码块 {} 里面定义的变量,只会在当前代码块有效,如果外层作用域下想访问该变量,会报引用错误异常。
  • 使用关键字 let 或 const 定义块级作用域的变量。

案例:

结果为:

变量b是在if里面声明的,但是在else和if外都可以访问

如果把var换成let,如下示例:

 结果为:

变量b只可以在声明的{}中使用

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-07-28 21:17  Lamb~  阅读(505)  评论(0)    收藏  举报