作用域 作用域链

128 阅读2分钟

本篇主要描述作用域和作用域链相关知识

什么是作用域?

"域"有区域的意思代表一块独立区域,代码中一些变量函数只在某个区域可见,其他区域访问不到,所以作用域可以起到隔离变量的作用,不同作用域下同名变量不会有冲突。在ES6 之前只有全局作用域和函数作用域,ES6之后新增了块级作用域,通过let和const定义的变量具有块级作用域。

  • 全局作用域

    • 最外层函数,在最外层函数外面定义的变量
    • 末定义直接赋值的变量
    • window对象下的属性
    • 一般不推荐,造成变量污染
  • 函数作用域

    • 声明在函数内部的变量,外部无法访问,除了闭包
    • 内层作用域可以访问外层作用域的变量,反之不行
  • 块级作用域

    • let const声明的变量,不会提升到代码块顶部
    • 不能重复声明
    • 应用场景:for循环内实现块级作用域,每次循环 都是单独的块级作用域不会被覆盖

什么是作用域链?

某个变量在当前作用域中未找到,就会到创建fn函数的那个作用域中取父级作用域中查找,一层一层向上寻找,直到全局作用域也没有就返回undefined。这种一层一层的关系,就是作用域链。这里需要注意不是去调用该函数的作用域找,而是创建该函数的作用域。作用域是静态的不是动态的。

作用域链和执行上下文有什么关系?

首先JavaScript是解释型语言,它的执行可以分为两个阶段:

  • 解释阶段:词法分析、语法分析、作用域规则确定
  • 执行阶段:创建执行上下文、执行函数代码、垃圾回收

可以看到,作用域链在解释阶段就确定了,是静态的;而执行上下文是执行阶段执行函数之前才确定,属于动态的,所以常说的this指向也是动态的。总的来说同一个作用域下,不同的调用会产生不同的执行上下文环境,从而产生不同的变量的值。

具体的执行上下文相关知识链接