变量提升与函数提升
变量声明提升:通过var定义(声明)的变量,在定义语句之前就可以访问到,值为undefined;
函数声明提升:通过function声明的函数,在之前就可以直接调用
注意:必须是function声明的函数
var myfun = function (){
} //不能提前调用,算作变量提升
先执行变量提升,再执行函数提升
记住一句话:函数提升优先级高于变量提升,且不会被同名变量声明覆盖,但是会被变量赋值后覆盖
var和function声明的变量创建在全局对象中,而let`const\class`声明的变量创建在全局scope当中
查找变量的时候,会先到scope中找变量,查找不到再到全局对象中查找
执行上下文
JavaScript 在执行语句之前,经过一系列的“准备”,为代码执行创造一个“教室”——执行上下文
代码分类(根据位置来分)
- 全局代码
- 函数代码 也叫局部代码
全局执行上下文
在执行全局代码前将window确定为全局执行上下文
对全局数据进行处理
1. `var`定义的全局变量, ==> undefined ,添加为window的属性
2. function声明的全局函数 ==>赋值(fun),添加为window的方法
3. this ==>赋值(window)
开始执行全局代码
函数执行上下文
在调用函数,准备执行函数体之前,创建函数执行上下文对象,在调用的时候产生函数执行上下文,函数调用结束后就会自动释放。
对局部数据进行预处理
1. 形参变量 ==> 赋值(实参) ==> 添加为执行上下文的属性
2. arguments ==>赋值(实参列表) ,添加为执行上下文的属性
3. `var`定义的全局变量, ==> undefined ,添加为执行上下文的属性
4. function声明的全局函数 ==>赋值(fun),添加为执行上下文的方法
5. this ==>赋值(调用函数的对象)
开始执行函数体代码
执行上下文栈
执行上下文的个数=N(调用函数的个数)+1(window)
在全局代码执行前,JS引擎会创建一个栈来管理所有产生的执行上下文对象
<script>
var a = 10;
var bar = function(x){
var b = 5;
foo(x + b);
}
var foo = function(y){
var c = 5;
console.log(a + c + y)
}
bar(10)''
</script>
如图所示:当前运行的总是栈顶的
执行栈栈顶的执行上下文称为当前执行上下文
JS代码总在当前执行上下文中运行
4种情况会创建新的执行上下文:
- 进入全局代码
- 进入function函数体代码
- 进入eval函数参数代码
- 进入module代码
作用域
它就是一块儿地盘,显示一个代码所在的区域,与执行上下文不同,它是静态的,在我们编写代码的时候就已经确定了。作用是隔离变量,不同作用域下同名变量不会有冲突。
全局作用域
函数作用域
块作用域(ES6之后)
作用域的个数=N(声明函数的个数)+1(window)
作用域链
多个上下级关系的作用域形成的链,它的方向是从下到上的(从内到外),查找变量的时候,沿着作用域链来找
变量的查找规则:
在当前作用域下的执行上下文中查找对应的属性,如果有就直接返回,否则进入上一级作用域的执行上下文中查找对应的属性,若没有,就一直向上查找,直到全局作用域链,若出现了还找不到的情况,就抛出异常。
\