一、作用域
1、什么是作用域
变量起作用的范围和区域
2、作用
隔离变量,不同作用域下同名变量不会冲突。
3、分类
(1)全局作用域
无论在哪都能访问,存在script标签对中;
全局作用域在网页打开时创建,在网页关闭时销毁;
全局对象是window代表的是整个浏览器窗口。
在全局作用域中使用var所创建的变量都会作为window对象的属性保存;全局作用域中所有的函数都会作为window对象的方法保存。
(2)函数作用域
函数调用时创建,调用结束作用域随之销毁;
每调用一次产生一个新的作用域,之间相互独立;
函数内部定义的变量外部不能访问,只能内访外,外不能访内。
(3)块级作用域
使用let或const声明的变量
二、作用域链
1、什么是作用域链?
整个作用域形成的关系叫做作用域链,寻找变量的过程。
2、作用域链作用?
用来保证——变量和函数在执行环境中有序访问。
3、寻找变量的过程
使用变量—>当前作用域找–>找不到上一级…–>全局作用域—>报错
三、预解析
1、什么是预解析?
JS引擎在JS代码正式执行之前会做一些预解析的工作。
预解析分为全局预解析和局部预解析
(1)提升以function开头的整个函数,函数在预解析的时候已经定义。
(2)提升以var开头的变量
(3)函数重名会覆盖,变量重名会忽略
(4)表达式定义的函数也是当做变量去解析
四、执行上下文
1、什么是执行上下文?
代码执行前,先会准备代码的执行环境,然后代码才会一行一行执行。
代码的执行环境称作执行上下文。
执行上下文包括:
(1)收集变量,生成变量对象
(2)确定this指向
(3)确定自己的作用域链。
2、分类
(1)全局执行上下文
- 将window确定为全局执行上下文对象
- var声明的全局变==>undefined,添加为window的属性
- Function声明的全局函数,赋值(fun),添加为window的方法
- this赋值window
- 开始执行代码
(2)函数执行上下文
- 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
- 形参变量==》赋值(实参),添加为执行上下文的属性 Arguments==赋值(实参列表),添加为执行上下文的属性
- var声明的局部变量==》undefined,添加为执行上下文的属性
- function声明的函数,赋值(fun),添加为执行上下文的方法。
- this=》赋值,调用者对象。
3、执行上下文栈
在全局代码执行前,JS引擎会创建一个栈来管理所有的所有的执行上下文对象。
程序为了管理执行上下文,确保程序的执行顺序。
var a = 10 // 1、进入全局执行上下文
var fn1=function(){
var b =5
fn2(x+b) // 2、进入f2执行上下文
}
var fn2 =function(y){
var c =5
console.log(a+c+y)
}
f1(10) // 3、进入f1函数执行上下文
全局执行上下文只有一个,上面是函数执行函数,全局执行上下总是在底部。
当前执行总是占顶部,代码执行完出栈。
4、执行上下文流程
(1)代码执行前,先创建全局执行上下文环境
- 收集变量,生成变量对象(变量,函数)
- this指向window
- 创建作用域链
- 在全局执行上下文(window确定后),将其添加到栈中(压栈)
(2)如果出现了函数调用,创建局部执行上下文
- 收集形参,Arguments,变量,函数
- 确定this指向
- 创建作用域链
- 在函数执行上下文创建后,将其添加到栈中(压栈)
在当函数执行完成后,将栈的顶级对象移出(出栈),当所有的代码执行完成后,栈中只剩window。
执行上下文是动态创建的,尤其是针对函数,每调用一次函数都会创建一次执行上下文。
五、作用域与执行上下文
作用域是静态的,只要函数定义好了就一直存在,且不会再变化。
执行上下文是动态创建的,尤其是针对函数,每调用一次函数都会创建一次执行上下文。
全局作用域---->预解析—>全局执行上下文环境—>全局的变量对象{var ,function ,函数参数,this的指向}----->函数定义---->局部作用域---->出现了函数调用----->局部局解析—>局部的执行上下文环境---->局部的变量对象{var ,function ,函数参数,this的指向}