本篇主要描述作用域和作用域链相关知识
什么是作用域?
"域"有区域的意思代表一块独立区域,代码中一些变量函数只在某个区域可见,其他区域访问不到,所以作用域可以起到隔离变量的作用,不同作用域下同名变量不会有冲突。在ES6 之前只有全局作用域和函数作用域,ES6之后新增了块级作用域,通过let和const定义的变量具有块级作用域。
-
全局作用域
- 最外层函数,在最外层函数外面定义的变量
- 末定义直接赋值的变量
- window对象下的属性
- 一般不推荐,造成变量污染
-
函数作用域
- 声明在函数内部的变量,外部无法访问,除了闭包
- 内层作用域可以访问外层作用域的变量,反之不行
-
块级作用域
- let const声明的变量,不会提升到代码块顶部
- 不能重复声明
- 应用场景:for循环内实现块级作用域,每次循环 都是单独的块级作用域不会被覆盖
什么是作用域链?
某个变量在当前作用域中未找到,就会到创建fn函数的那个作用域中取父级作用域中查找,一层一层向上寻找,直到全局作用域也没有就返回undefined。这种一层一层的关系,就是作用域链。这里需要注意不是去调用该函数的作用域找,而是创建该函数的作用域。作用域是静态的不是动态的。
作用域链和执行上下文有什么关系?
首先JavaScript是解释型语言,它的执行可以分为两个阶段:
- 解释阶段:词法分析、语法分析、作用域规则确定
- 执行阶段:创建执行上下文、执行函数代码、垃圾回收
可以看到,作用域链在解释阶段就确定了,是静态的;而执行上下文是执行阶段执行函数之前才确定,属于动态的,所以常说的this指向也是动态的。总的来说同一个作用域下,不同的调用会产生不同的执行上下文环境,从而产生不同的变量的值。