在js代码进行编译的时候,存在有变量提升和函数提升 变量提升:通过var定义的变量,在定义语句之前就可以访问到,这个时候值为undefined 函数提升:通过function声明的函数,在之前就可以直接调用,这个时候值为已经定义过的函数
那么变量提升和函数提升是如何产生的呢?此时需要提到js的执行上下文
首先,执行上下文的操作是一个对js代码进行预编译的操作,是js代码运行之前的一个过程 上下文可以理解为当前页面中从上到下的代码 js的执行上下文分为全局执行上下文和函数执行上下文
全局执行上下文流程: 在执行全局代码前将window确定为全局执行上下文 对全局数据进行预处理(顺序执行以下三步) var定义的全局变量==>undefined,添加为window的属性 function声明的全局函数==>赋值(fun),添加为window的方法 this==>赋值(window) 开始执行全局代码
函数执行上下文流程: 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(不是真实存在的虚拟对象,存在于栈中) 对局部数据进行预处理(顺序执行以下五步) 形参变量==>赋值(实参) == > 添加为执行上下文的属性 arguments==>赋值(实参列表),添加为执行上下文的属性 var定义的局部变量==>undefined,添加为执行上下文的属性 function声明的全局函数==>赋值(fun),添加为执行上下文的方法 this==>赋值(调用函数的对象) 开始执行函数体代码
执行上下文栈: js的执行上下文的操作的底层是通过执行上下文栈实现的 在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象 在全局执行上下文(window)确定后,将其添加到栈中(压栈) 在函数执行上下文创建后,将其添加到栈中(压栈) 在当前函数执行完后,将栈顶的对象移除(出栈) 当所有代码执行完后,栈中只剩下window
最后附加一道关于变量提升的面试题:
var c = 1; function c(c) { console.log(c); } c(2);此时的代码不会运行出2,而是会报错,实例运行过程可以理解为:
var c; function c(c) { console.log(c); } c = 1; c(2);解释: 在进行执行上下文预编译的时候,会按照顺序先进行全局执行上下文再执行函数执行上下文,所以var c首先会被赋值为undefined,之后在完成了函数执行上下文后,就会执行代码,在执行代码的时候c又会被赋值为1,所以此时调用 c(2) 是肯定调用不到的。
注:本文是在我学习b站js高级相关视频后总结出来的,如果侵权了我就删掉