☀️作用域是什么?作用域链又是什么?你怎么理解?

Posted °PJ想做前端攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了☀️作用域是什么?作用域链又是什么?你怎么理解?相关的知识,希望对你有一定的参考价值。


面试官:跟我说说你对作用域和作用域链的理解吧。

我:。。。💥


作用域

作用域就是代码的执行环境,全局执行环境就是全局作用域,函数的执行环境就是私有作用域,它们都是栈内存。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。

  1. 全局作用域

    • 最外层函数和最外层函数外面定义的变量拥有全局作用域
    • 所有未定义直接赋值的变量自动声明为全局作用域
    • 所有window对象的属性拥有全局作用域
    • 全局作用域有很大的弊端,过多的全局作用域变量会污染全局命名空间,容易引起命名冲突
  2. 函数作用域

    • 函数作用域声明在函数内部的变量,一般只有固定的代码片段可以访问到
    • 作用域是分层的,内层作用域可以访问外层作用域,反之不行
  3. 块级作用域

    • 使用ES6中新增的let和const指令可以声明块级作用域,块级作用域可以在函数中创建也可以在一个代码块中的创建(由{ }包裹的代码片段)
    • let和const声明的变量不会有变量提升,也不可以重复声明
    • 在循环中比较适合绑定块级作用域,这样就可以把声明的计数器变量限制在循环内部。

作用域链

在当前作用域中查找所需变量,但是该作用域没有这个变量,那这个变量就是自由变量。如果在自己作用域找不到该变量就去父级作用域查找,依次向上级作用域查找,直到访问到window对象就被终止,这一层层的关系就是作用域链。作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问,通过作用域链,可以访问到外层环境的变量和函数。作用域链的本质上是一个指向变量对象的指针列表。变量对象是一个包含了执行环境中所有变量和函数的对象。作用域链的前端始终都是当前执行上下文的变量对象。

全局执行上下文的变量对象(也就是全局对象)始终是作用域链的最后一个对象。

总结

1.作用域链存储的就是执行上下文的集合

2.当前作用域中没有使用未在在作用域定义的变量时,会沿着作用域链向上找

代码理解

var z = 1 
//1.tim 定义 tim.[[scope]] = GO:{z:1,tim:[Function: tim]}
function tim(){
  //3.cope定义 cope.[[scope]] = tim.[[scope]] = tim(AO):{cope:[Function: cope],y:undefined}=>GO
   function cope(){
       var x= 2;
         // 6.cope(AO)上没有y属性,就会沿着作用域链往上找,一直没有就会挂载在GO上
       y=3
   }
  //4.tim(AO):{cope:[Function: cope],y:4}
   var y = 4
   //5.cope.[[scope]] = cope(AO):{x:undefined}=>tim(AO)=>GO
   cope()
  //7.tim(AO):{cope:[Function: cope],y:4}
   console.log(y)  // 3
}
//2.tim 执行 tim.[[scope]] = tim(AO):{cope:[Function: cope],y:undefined}=>GO:{z:1,tim:[Function: tim]}
tim()

以上是关于☀️作用域是什么?作用域链又是什么?你怎么理解?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript内部属性[[Scope]]与作用域链及其性能问题

js函数作用域和块级作用域的区别

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

(转)JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

作用域链