前言
预编译 是JavaScript中一个重要的概念指的是在代码实际执行之前,JavaScript引擎会先进行一系列的准备工作,以确保代码能够按照预期运行。这个过程主要包括变量声明 的提升(hoisting)和函数声明 的提升,以及执行环境的初始化 。全局预编译 和函数预编译 也不太相同,今天通过5分钟就让你搞懂这个知识点。
全局预编译
我先讲一下这里全局预编译的过程:
1. 创建全局执行上下文对象 GO
2. 找变量声明,变量名作为Go的属性名,值为undefined( 变量提升 )
3. 在函数声明,函数名作为Go的属性名,值为函数体
这里属性和方法名都是存在GO对象中,你要先明白一个先前知识点就是对象中不能存在相同的属性名,如果已经存在了则会对之前的属性值进行覆盖.比如
ini
obj.a =1
obj.a =2
console.log(a)//这里打印的是2
是不是很简单,我们一起用一个例子来先试试看。
ini
console.log(str);
var str ="123";
console.log(str);
来!跟着我一起按照上面的步骤思考一下答案:
rust
1-首先全局编预译在全文创建一个函数体
GO ={
}
2-找变量声明,变量名作为Go的属性名,值为undefined( 变量提升 )
//这里就将str进行变量提升
GO ={
str : undefined
}
3-在函数声明,函数名作为Go的属性名,值为函数体
//这里没有函数所以就可以跳过啦
全局预编译就完成了!
预编译完成之后然后就开始执行代码编译部分
首先遍历到console.log(str);
此时str的值为undefined,所以打印的是undefined,
然后遍历var str ="123",则obj对象里面的str就变成了123.
GO ={
str :"123"
}
最后执行打印str就输出打印123
是不是感觉很简单,接下来跟我一起来一点进阶的
ini
console.log(f);
var f = 123;
console.log(f);
function f(){}
console.log(f);
注意别掉队,要开始发车了!
ini
1-首先全局编预译在全文创建一个函数体
GO ={
}
2-找变量声明,变量名作为Go的属性名,值为undefined( 变量提升 )
GO ={
f : undefined
}
3-在函数声明,函数名作为Go的属性名,值为函数体
GO ={
f : function f(){}
}
预编译完成,开始执行代码
console.log(f);//打印function f(){}
var f = 123;//赋值f为123
则GO ={
f:123
}
console.log(f);//打印为123
function f(){}//这里只是方法声明,在预编译已经执行完成,所以这里不执行
console.log(f);//打印123
如何?你有没有写对呢?
函数预编译
函数预编译就是执行函数时开始进行,而不是声明函数时开始预编译这个要搞明白。
我先讲一下这里函数预编译的过程:
1-创建一个AO对象
2-寻找变量,GO对象里面创建属性为变量,初始化赋值为undefined(进行变量声明( 变量提升 ))
3-形参和实参进行统一(将GO里面创建属性为形参的名字,值为形参值)
4-寻找函数声明,GO对象里面创建属性为函数名,初始化赋值为function 变量名(){}(进行函数声明(函数提升,整体提升))
老规矩先来一个简单题:
javascript
function fn(str){
console.log(str);
var str ="123";
console.log(str);
function str(){
}
}
fn("abc");
scss
1-创建一个AO对象
AO ={}
2-寻找变量,GO对象里面创建属性为变量,初始化赋值为undefined(进行变量声明( 变量提升 ))
AO ={
str : undefined;
}
3-形参和实参进行统一(将GO里面创建属性为形参的名字,值为形参值)
AO ={
str :"abc"
}
4-寻找函数声明,GO对象里面创建属性为函数名,初始化赋值为function 变量名(){}
AO ={
str :function str(){}
}
预编译已完成开始执行代码
第一行console.log(str)则打印的是function str(){}
第二行进行str赋值为123
第三行console.log(str)则打印则是123
第四行函数声明不执行
你以为我要开始第二个简单题了吗?错!我开始出一题融合难题给你了
首先我的再次声明函数预编译就是执行函数时开始进行,而不是声明函数时开始预编译 这个要搞明白。 所以顺序是先全局预编译,然后进行代码执行,执行到函数方法时,才开始函数预编译!如果局部对象中不存在的属性将会去上一级对象中查找,直到查找到全局对象。 没有则报错!
综合题
ini
console.log(str);
var str;
str();
function str(str){
console.log(str);
str =123;
}
console.log(str);
老规矩开始分析
scss
1. 创建全局执行上下文对象 GO
GO ={}
2. 找变量声明,变量名作为Go的属性名,值为undefined( 变量提升 )
GO ={
str : undefined
}
3. 在函数声明,函数名作为Go的属性名,值为函数体
GO ={
str : function str(){}
}
全局预编译完成!开始执行代码
第一行 console.log(str)打印function str(){}
第二行 var str;变量声明并没有进行赋值操作则不执行
第三行 str();开始执行str函数
进行函数预编译
1-创建一个AO对象
AO ={}
2-寻找变量,GO对象里面创建属性为变量,初始化赋值为undefined(进行变量声明( 变量提升 ))
没有变量声明则不操作
3-形参和实参进行统一(将GO里面创建属性为形参的名字,值为形参值)
没有形参则不操作
4-寻找函数声明,GO对象里面创建属性为函数名,初始化赋值为function 变量名(){}
没有函数声明则不操作
开始执行函数代码
console.log(str);AO对象中没有str属性则去上一级对象中也就是全局对象找str,找到打印
function str()
str =123 没有str属性则去上一级对象中也就是全局对象找str,赋值123
函数执行完毕
console.log(str);打印123
怎么样你想对了没!
总结
通过预编译,JavaScript引擎能够准确地知道哪些变量和函数在哪个作用域内可用,有助于避免变量污染和命名冲突。总的来说是必须掌握的知识。如果你能把上面的例子都理解明白的话我相信你可以掌握这个知识点了。如果还喜欢的话请点赞和关注吧!以后也会更新5分钟系列的>_<.