概念
词法作用域
- 又称静态作用域
- 变量被创建时就确定好了,非执行阶段确定的
- 我们写好代码它的作用域就确定了
- js遵循词法作用域,相同层级foo,bar没有办法访问到彼此的块级
-
var a = 2 function foo() { console.log(a) } fuction bar() { var a = 3 foo() }
-
动态作用域
js不支持动态作用域,可以通过闭包的方式来模拟动态作用域
作用域
即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合
- 作用域决定了代码区块中变量和其他资源的可见性
全局作用域(Global Scopel)
- 任何不在函数中或是大括号中声明的变量,都是在全局作用域下
- 范围:任何地方
局部作用域(Local Scope)
- 也叫局部作用域
- 一个变量是在函数内部声明的,它就在这个函数作用域下
- var,没有var 是全局作用域
- 范围:该变量只能在函数内部访问,不能在函数以外去访问
块级作用域
- 在大括号中使用let和const声明的变量存在于块级作用域中(ES6提出)
- 范围:大括号内
作用域链
当js查找变量的时候,js引擎会现在当前作用域下查找该变量,没有的话,去它的上级作用域,直到找到该变量,或者已经到了全局作用域,如果全局作用域还找不到,它会隐式声明变量(非严格),或直接报错
预解析(变量提升)
- js代码是由js解析器来执行的,分为:预解析过程、代码处理过程
- 预解析过程
- 把变量提升到当前作用域最前面,只会声明,不会赋值
- 把函数提升到当前作用域最前面,只会声明,不会调用
- 提升时,先变量后函数
- 预解析:先把所有带var、function声明的变量进行提前声明
- 在函数执行的时候,先进行形参赋值,再进行预解析
代码
fn();
var fn = 100;
function fn(){
fn = 200;
}
console.log(fn); //100
function fn(a){
console.log(a)
var a=123
console.log(a)
function a(){}
console.log(a)
}
fn(1)
function test(a,b){
console.log(b)
a=3;
b=2;
console.log(b)
function b(){}
console.log(b)
}
test(1)
function test(a,b){
console.log(b)
var b=234
console.log(b)
b=234
var b=function(){}
console.log(b)
}
test(1)
//undefined
//234
//ƒ (){}
参考链接
【经典面试题】JS作用域、作用域链、预解析_作用域与预解析面试题-CSDN博客
JavaScript 函数作用域(面试常考,还不来看) - 知乎 (zhihu.com)
js作用域面试题 - 前端奋斗者 - 博客园 (cnblogs.com)
以上两篇配合使用更佳