o变量提升与函数提升
1. 变量声明提升
在全局作用域中,使用 var 关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值
在函数作用域中,使用 var 关键字声明的变量,会在调用函数时,其他语句执行之前被声明
值:undefined
例子:
<script>
console.log(a);//undefined
var a = 5;
</script>
2. 函数声明提升
在全局作用域中,使用函数声明创建的函数(FUNCTION FUN(){}),会在所有的代码执行之前被创建
在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了
值:函数定义
例子:
<script>
f();//f()
function f(){
console.log('f()');
}
</script>
造成变量提升的本质原因是因为JavaScript引擎在代码执行前会有一个解析的过程,创建执行的上下文,初始化一些代码在执行时所需要使用的对象。
例子:
<script>
// 测试题1
function a(){}
var a;
console.log(typeof a);
// 测试题2
if(!(b in window)){
var b = 1
}
console.log(b);
// 测试题3
var c = 1
function c(c){
console.log(c);
var c = 3
}
// c(2)
console.log(typeof c);
</script>
我用了两个月的时间才理解 let - 知乎 (zhihu.com) |
用var声明的变量,不赋具体的值,总会比用function声明的函数后输出,因为在被创建的同时,会直接将函数赋值给创建的函数,相当于比var多了一个赋值的步骤 |
用var声明的变量,赋具体的值,总会比用function声明的函数先输出,因为function函数已经被创建好了,最后又对变量做了一个赋值操作 |
执行上下文
全局执行上下文
1. 在代码执行前,创建全局执行上下文Window
2. 对全局数据进行预处理
用 var 声明的变量 在所有代码执行之前被声明 ,赋值为undefined,添加为Window的属性
用 function 声明的函数 在所有代码执行之前被创建,值为整个函数定义,添加为Window的方法
this = Window
3. 开始执行全局代码
函数执行上下文
1. 在调用函数,准备执行函数体之前,创建对应的函数执行上下文
2. 对局部数据进行预处理
将实参赋值给形参变量,添加为执行上下文的属性
将实参列表赋值给 arguments,添加为执行上下文的属性
用 var 声明的变量 在所有局部代码执行之前被声明 ,赋值为undefined,添加为执行上下文的属性
用 function 声明的函数 在所有局部代码执行之前被创建,值为整个函数定义,添加执行上下文的方法
this = 调用函数的对象
3. 开始执行函数体代码
执行上下文栈
1、在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象
2、在全局执行上下文对象(Window)确立后,将其压入栈中
3、在函数执行上下文创建后,将其压入栈中
4、在当前函数执行完后,将当前函数执行上下文对象出栈
5、当所有的代码执行完后,栈中只剩下window
图例:
示例:
<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>