web前端学习 JS预编译,执行上下文,变量函数提升
这几天听学长们讲课,发现很多东西没了解到
自己也一直没写博客的习惯,正好从现在开始慢慢养成这个习惯
JavaScript运行
- 语法分析
- 预编译
- 解释执行
变量提升
函数及变量的声明都将被提升到函数的最顶部。本质还是受到了预编译影响
下面这个例子可能不是很好,但就是这个让我了解到这些问题
var a = 1;
function b(){
a = 10;
return;
function a(){
console.log("1st"+a);
}
}
b();
console.log("this="+a);//this=1
var a = 1;
//全局执行上下文
function b(){
a = 10;
return;
function a(){
console.log("1st"+a);
}
}
b();
//执行b();=>函数上下文(全局执行上下文被压入调用栈底)
//function b(){
// a = 10;
// return;
// function a(){
// console.log("1st"+a);
// }
//}
//a首先为undefined,没有var let等字段,在函数内部找到了function a,此时a被赋值为函数,变成函数b中的局部变量 接着a赋值为10,return后函数上下文环境出栈销毁,最后
console.log("this="+a);//this=1,输出a=1
用伪代码看可能会好一点
GO = { //GO全局对象(Global Object)
a: undefined,
b : function b(){
//...
}
}
GO = {
a : 1,
b: function b(){
//...
}
}
//--> 进入函数执行上下文 预编译
AO = {
a: undefined,
}
//-->
//此时a被赋值为函数,成为 函数b中的局部变量,没有覆盖全局对象中的a
AO = {
a = function a(){
//....
}
}
//--> 执行解释
AO = {
a : 10,
}
//-->return; 函数执行上下文出栈销毁
GO = {
a:1
}
执行上下文
执行上下文有且只有三类,全局执行上下文,函数上下文,eval上下文(很少用)
全局执行上下文
全局执行上下文只有一个,在客户端中一般由浏览器创建=>window
对象
window对象还是var声明的全局变量的载体
函数上下文
每当一个函数被调用时都会创建一个函数上下文
同一个函数被多次调用,都会创建一个新的上下文
**执行上下文栈
**用于存储代码执行期间创建的所有上下文
-
创建阶段
This绑定=>创建词法环境组件=>创建变量环境组件
词法环境用来储存函数声明和变量(
let
和const
)绑定,变量环境用来储存var
变量绑定函数声明与var声明的变量在创建阶段已经被赋予了一个值,var声明被设置为了undefined,函数被设置为了自身函数,而let ,const被设置为未初始化。
-
执行阶段
变量赋值=>函数引用=>执行其他代码
-
销毁阶段
预编译
预编译确实在script代码内执行前发生了 但是它大部分会发生在函数执行前
var a = 1;
console.log(a);
function test(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
}
var c = function (){
console.log("I at C function");
}
console.log(c);
test(2);
预编译(全局执行上下文)
//抽象描述
GO/window = { //GO全局对象(Global Object)
a:undefined,
c:undefined,// var b = function(){} 为赋值语句,函数也是一种数据类型,所以变量c在预编译时为undefined var b = function b(){}也同理 预编译时为undefined
test:function(a){
console.log(a);
var a = 123;
console.log(a);
function a(){}
console.log(a);
var b = function(){}
console.log(b);
function d(){}
}
}
解释执行代码(到test(2)之前)
//抽象描述
GO/window = {
a:1,
c:function(){
console.log("I at C function");
},
test:function(a){
//....
}
}
执行到test(2),
预编译(函数上下文)
//抽象描述
AO = {
a:undefined,
b:undefined,
}
—>
AO = {
a: 2,//实参形参统一
b: undefined,
}
—>
AO = {
a: function a(){} //a,d函数声明,并赋值函数体
b:undefined
d: function d(){}
}
解释执行(test(2))
AO = {
a:function a(){}
b:undefined
d:function d(){}
}
--> //var = 123 赋值
AO = {
a:123,
b:undefined,
d:function d(){}
}
--> //var b = function(){}
AO = {
a:123,
b:function(){}
d:function d(){}
}
执行结果
1
ƒ(){
console.log("I at C function");
}
ƒ a() {}
123
123
ƒ () {}