执行上下文
某个函数或全局代码的执行环境,该环境中包含执行代码所需要的信息。
当执行一个函数或者全局代码时,需要建立执行上下文
call stack(执行上下文栈)
组织管理程序运行过程中执行上下文,以栈的形式存储。新建的执行上下文在栈顶,执行完之后出栈被销毁。
开始执行js文件时,首先创建全局window的执行上下文,存放在执行上下文的栈底;执行函数时,创建对应函数的执行上下文,添加至栈顶;在栈顶的永远是正在执行的函数的执行上下文;函数执行完毕后,对应的执行上下文被销毁,直至全局的执行上下文被销毁,js执行完成。
执行上下文建立过程
创建阶段
1.vo(variavle object)变量对象,存放的是函数或者全局代码执行过程中需要的变量
-1.确定函数形参,并赋值;确定arguments对象
-2.确定函数中所有函数字面量声明(1.该函数必须为字面量声明 2.如果出现同名变量,直接覆盖)
-3.确定函数中所有var声明变量,将其提取至上下文,值为undefined(如果出现同名属性,忽略)
2.建立作用域链(scope)
3.this指向
代码执行阶段
顺序执行代码,变量赋值
注:let声明的变量不会被提升
this的几种情况
1.全局环境下指向window
2.函数中this
-1.谁调用它就指向谁,函数调用者为对象时;
-2.当函数独立调用时,该函数内部的this指向undefined,在非严格模式下,this指向undefined时,会自动指向window;
3.call/apply
-1.改变this指向 fn.call(obj,argument1,argument2...) /fn.apply(obj,arguments) ==>改变指向后,fn可以通过this.xxx访问obj
内部属性
2.call/apply 传参形式不同
4.构造函数中this
通过构造函数使用new关键字时,会经历以下四个阶段:
- 创建一个新对象
- 将构造函数的this指向该对象
- 为对象添加属性、方法等
- 返回这个对象
闭包
当内部函数引用(内部函数使用了外部函数中局部变量)被保存到外部必然形成闭包
缺点:作用域链不释放,造成内存泄漏
优点:私有化变量
实现共有变量(累加器)
模块化开发,防止污染全局